diff --git a/OBE-BUSINESS/src/com/gx/obe/web/service/BidPriceResultService.java b/OBE-BUSINESS/src/com/gx/obe/web/service/BidPriceResultService.java
index 03cc2a97b93e5e36ec25b0aa4b7c1e72282579d4..a17dbc313c7945d0e07e4d84b480c65dab8b729e 100644
--- a/OBE-BUSINESS/src/com/gx/obe/web/service/BidPriceResultService.java
+++ b/OBE-BUSINESS/src/com/gx/obe/web/service/BidPriceResultService.java
@@ -1,5 +1,6 @@
 package com.gx.obe.web.service;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
@@ -23,6 +24,7 @@ import com.gx.obe.web.vo.SaveSubBidPriceResultVo;
 import com.gx.obe.web.vo.SaveSupplierInputBidPriceResultVo;
 import com.gx.obe.web.vo.SaveSupplierInputEvaluationPriceResultVo;
 import com.gx.obe.web.vo.UpdateAssignPropertyVo;
+import com.gx.obe.web.utils.ObeHttpUtils;
 
 /** 
  * @Description: 投标报价数据接口
@@ -501,4 +503,21 @@ public class BidPriceResultService {
 			return false;
 		}
 	}
+	
+	/**
+	 * @Description: 修正投标报价
+	 * @author chenxw
+	 * @param id
+	 * @param finalBidPrice
+	 * @param modifyReason
+	 * @return 
+	 */
+	public boolean modifyBidPrice(String id, BigDecimal finalBidPrice, String modifyReason) {
+		Map<String, Object> param = new HashMap<String, Object>();
+		param.put("id", id);
+		param.put("finalBidPrice", finalBidPrice);
+		param.put("modifyReason", modifyReason);
+		return ObeHttpUtils.getBoolean(URL.concat("/modifyBidPrice"), param);
+		
+	}
 }
diff --git a/OBE-BUSINESS/src/com/gx/obe/web/utils/ObeHttpUtils.java b/OBE-BUSINESS/src/com/gx/obe/web/utils/ObeHttpUtils.java
index 4075bd90c08837a6659ae9843ba2339eb167ddd7..ac335febe14ee9ad89662056ac95f736205bbd7b 100644
--- a/OBE-BUSINESS/src/com/gx/obe/web/utils/ObeHttpUtils.java
+++ b/OBE-BUSINESS/src/com/gx/obe/web/utils/ObeHttpUtils.java
@@ -51,4 +51,14 @@ public class ObeHttpUtils {
 		return new ArrayList<>();
 	}
 	
+	public static boolean getBoolean(String path, Map<String, Object> param) {
+		String strWebServerUrl = Constants.getServiceUrl(path);
+		try {
+			return ResultStatus.getReultStatusBoolean(NetworkRequest.get(strWebServerUrl, param));
+		} catch (Exception e) {
+			logger.error(e.getMessage(), e);
+			return false;
+		}
+	}
+	
 }
diff --git a/OBE-COMPONENTS-CORE/META-INF/MANIFEST.MF b/OBE-COMPONENTS-CORE/META-INF/MANIFEST.MF
index 4aa266f4bfb4826e68bcd9013afcdcadd67f015a..99f30cb88cc42f879fef9874cbb95b5cbe23d33f 100644
--- a/OBE-COMPONENTS-CORE/META-INF/MANIFEST.MF
+++ b/OBE-COMPONENTS-CORE/META-INF/MANIFEST.MF
@@ -68,3 +68,4 @@ Bundle-ClassPath: .,
  lib/jackson-core-2.9.0.jar,
  lib/jackson-databind-2.9.0.jar
 Bundle-ActivationPolicy: lazy
+Import-Package: com.gx.obe.datastruct.tree
diff --git a/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/Constants.java b/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/Constants.java
index 09eed6ac757d4b677b5a0512c1082ab54e72f2e4..afe6244ae97d4dbba8b11065cf0bb6a384d7858b 100644
--- a/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/Constants.java
+++ b/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/Constants.java
@@ -194,5 +194,20 @@ public class Constants {
 	
 	public static final String TIANYAN_CHECK_NOTE = "TIANYAN_CHECK_NOTE.pdf";
 	
+	public static String ETB = ".etb";// 电子投标文件
+	public static String EZG = ".etb";//".ezg";// 电子资格投标文件
+	public static String EZB = ".ezb";// 电子招标文件
+	public static String ECN = ".enc";
+	public static String ENC = ".enc";
+	public static String XLS = ".xls";
+	public static String PDF = ".pdf";
+	public static String DOC = ".doc";
+	public static String DOCX = ".docx";
+	public static String XML = ".xml";
+	public static String LOG = ".log";
+	public static String XLSX = ".xlsx";
+	public static String ZIP = ".zip";
+	
+	
 }
 
diff --git a/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/enumeration/EvaluationStepEnum.java b/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/enumeration/EvaluationStepEnum.java
index e347e0665dc50a4d3850960e5255de38eb04551a..3d3550ab593f520e955eb47bb318f3064b5e4079 100644
--- a/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/enumeration/EvaluationStepEnum.java
+++ b/OBE-COMPONENTS-CORE/src/com/gx/obe/components/core/enumeration/EvaluationStepEnum.java
@@ -26,6 +26,8 @@ public class EvaluationStepEnum {
 	public static final String EDIT_PRICE = "17";// 价格评审
 //	public static final String REBIDPRICE = "18";// 再次报价
 	public static final String BUSINESS_VETO = "18";
+	public static final String APPRAISE_EXPERT = "19";// 评价专家
+	public static final String APPRAISE_MANAGER = "20";// 评价项目经理
 	public static final String FIXED_FACTOR = "21";// 定档
 	public static final String ASSOCIATION_QUERY = "22";// 关联查询评审步骤
 	
diff --git a/OBE-COMPONENTS-MESSAGES/bin/com/gx/obe/message/messages.properties b/OBE-COMPONENTS-MESSAGES/bin/com/gx/obe/message/messages.properties
index 86f6e059568a828e24bcf8d93375a214aa012401..6d44fabaf79ae4fc4522b66e80d60085fdc7e2e1 100644
--- a/OBE-COMPONENTS-MESSAGES/bin/com/gx/obe/message/messages.properties
+++ b/OBE-COMPONENTS-MESSAGES/bin/com/gx/obe/message/messages.properties
@@ -1826,3 +1826,5 @@ Yes=\u662F
 You=\u60A8
 ZipCode=\u90AE\u653F\u7F16\u7801
 ips_noOpenLiveing=\u672A\u5F00\u542F\u76F4\u64AD\uFF01
+Step_appraiseExpert=\u4e13\u5bb6\u8bc4\u4ef7
+Step_appraiseManager=\u9879\u76ee\u7ecf\u7406\u8bc4\u4ef7
diff --git a/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/Messages.java b/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/Messages.java
index c2a30e534f2eced9d34bd07b2ea4a9b62e693940..15d57024640c136c3be063898580ea3543cfd066 100644
--- a/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/Messages.java
+++ b/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/Messages.java
@@ -1885,6 +1885,8 @@ public class Messages extends NLS {
 	public static String ips_noOpenLiveing;
 	public static String RecommonedEvaluationComposite_text_text;
 	public static String RecommonedEvaluationTableComposite_text_text;
+	public static String Step_appraiseExpert;
+	public static String Step_appraiseManager;
 	
 	static {
 		// initialize resource bundle
diff --git a/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/messages.properties b/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/messages.properties
index 86f6e059568a828e24bcf8d93375a214aa012401..6d44fabaf79ae4fc4522b66e80d60085fdc7e2e1 100644
--- a/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/messages.properties
+++ b/OBE-COMPONENTS-MESSAGES/src/com/gx/obe/message/messages.properties
@@ -1826,3 +1826,5 @@ Yes=\u662F
 You=\u60A8
 ZipCode=\u90AE\u653F\u7F16\u7801
 ips_noOpenLiveing=\u672A\u5F00\u542F\u76F4\u64AD\uFF01
+Step_appraiseExpert=\u4e13\u5bb6\u8bc4\u4ef7
+Step_appraiseManager=\u9879\u76ee\u7ecf\u7406\u8bc4\u4ef7
diff --git a/OBE-UTILS/src/com/gx/obe/util/utils/Keys.java b/OBE-UTILS/src/com/gx/obe/util/utils/Keys.java
index c1b56a7548d2a6a7f4ae272445b99e0a87af7f13..c412c248ec3d8735d57d5d63c31cdeaf07e58f54 100644
--- a/OBE-UTILS/src/com/gx/obe/util/utils/Keys.java
+++ b/OBE-UTILS/src/com/gx/obe/util/utils/Keys.java
@@ -56,4 +56,8 @@ public class Keys {
 		return get(2);
 	}
 	
+	public static Keys of(Object... ks) {
+		return new Keys(ks);
+	}
+	
 }
diff --git a/OBE-UTILS/src/com/gx/obe/util/utils/PredicateUtils.java b/OBE-UTILS/src/com/gx/obe/util/utils/PredicateUtils.java
index ea9145837d6488cef5f46cc3ce4d5a7f776c86ad..6af6c7d23ae79b2831111cc769600ea223b459dc 100644
--- a/OBE-UTILS/src/com/gx/obe/util/utils/PredicateUtils.java
+++ b/OBE-UTILS/src/com/gx/obe/util/utils/PredicateUtils.java
@@ -29,4 +29,27 @@ public class PredicateUtils {
 		return t -> predicate.test(function.apply(t));
 	}
 	
+	
+	/**
+	 * @Description: 使用
+	 * @author chenxw
+	 * @param f
+	 * @param p
+	 * @return
+	 */
+	public static <T, R> Predicate<T> apply(Function<T, R> f, Predicate<R> p) {
+		return t -> p.test(f.apply(t));
+	}
+	
+	
+	/**
+	 * @Description: 大于
+	 * @author chenxw
+	 * @param higher
+	 * @return
+	 */
+	public static Predicate<Integer> higher(int higher) {
+		return t -> t > higher;
+	}
+	
 }
diff --git a/OBE-UTILS/src/com/gx/obe/util/utils/TerminalUtils.java b/OBE-UTILS/src/com/gx/obe/util/utils/TerminalUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..3e2caf4829e6ba99825a427685e838441d06ba62
--- /dev/null
+++ b/OBE-UTILS/src/com/gx/obe/util/utils/TerminalUtils.java
@@ -0,0 +1,58 @@
+package com.gx.obe.util.utils;
+
+import java.util.Map;
+
+import com.gx.obe.util.utils.EnumUtils;
+
+public enum TerminalUtils {
+	
+	/**
+	 * 项目管理
+	 */
+	TERMINAL_MANAGEMENT("00"),
+	/**
+	 * 开标工具
+	 */
+	TERMINAL_BIDOPENING("01"),
+	/**
+	 * 评标工具
+	 */
+	TERMINAL_EVALUATION("02"),
+	/**
+	 * 系统管理
+	 */
+	TERMINAL_SYSTEM("03"),
+	/**
+	 * 远程开标辅助工具
+	 */
+	TERMINAL_ASSISTOPENING("04"),
+	/**
+	 * 监督管理
+	 */
+	TERMINAL_SUPERVISE("05");
+	
+	private String key;
+	
+	private static TerminalUtils terminalType;
+	
+	private TerminalUtils(String key) {
+		this.key = key;
+	}
+	
+	public static Map<String, TerminalUtils> map = EnumUtils.toMap(values(), TerminalUtils::getKey);
+	
+	public String getKey() {
+		return key;
+	}
+	
+	public static void setTerminalType(TerminalUtils terminalType) {
+		TerminalUtils.terminalType = terminalType;
+	}
+	
+	public static TerminalUtils getTerminalType() {
+		return terminalType;
+	}
+	
+	
+	
+}
diff --git a/com.gx.obe.action/META-INF/MANIFEST.MF b/com.gx.obe.action/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..cca79de04929ad529aa1a14abd3e0b8c5291ef48
--- /dev/null
+++ b/com.gx.obe.action/META-INF/MANIFEST.MF
@@ -0,0 +1,19 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Action
+Bundle-SymbolicName: com.gx.obe.action;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: com.gx.obe.action.Activator
+Bundle-Vendor: GX
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ com.gx.obe.utils,
+ com.gx.obe.components.core,
+ com.gx.obe.business,
+ com.gx.obe.component,
+ com.gx.obe.bind;bundle-version="1.0.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: com.gx.obe.action
+Bundle-ActivationPolicy: lazy
+Export-Package: com.gx.obe.action.bean,
+ com.gx.obe.action.listener
diff --git a/com.gx.obe.action/build.properties b/com.gx.obe.action/build.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5f4af4c12f2be47c626539ee2608fd76e1a96c77
--- /dev/null
+++ b/com.gx.obe.action/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
+javacDefaultEncoding.. = UTF-8
\ No newline at end of file
diff --git a/com.gx.obe.action/src/com/gx/obe/action/Activator.java b/com.gx.obe.action/src/com/gx/obe/action/Activator.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8af5cdf3fdc00bd0c582dfeea1204cd45a76285
--- /dev/null
+++ b/com.gx.obe.action/src/com/gx/obe/action/Activator.java
@@ -0,0 +1,50 @@
+package com.gx.obe.action;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "com.gx.obe.action"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/com.gx.obe.action/src/com/gx/obe/action/bean/Action.java b/com.gx.obe.action/src/com/gx/obe/action/bean/Action.java
new file mode 100644
index 0000000000000000000000000000000000000000..58243649e4c63ca4e6de218d34e3ec706c41ee9f
--- /dev/null
+++ b/com.gx.obe.action/src/com/gx/obe/action/bean/Action.java
@@ -0,0 +1,187 @@
+package com.gx.obe.action.bean;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import com.gx.obe.action.listener.ActionListener;
+import com.gx.obe.util.utils.UuidUtils;
+import com.gx.obe.web.entity.auth.Menu;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.entity.tender.TenderProjectRuleEntity;
+import com.gx.obe.web.service.ProjectRuleService;
+import com.gx.obe.web.service.TenderProjectService;
+
+/**
+ * @Description:封装公共action接口 
+ * @author guoyr
+ */
+public abstract class Action {
+	private String id = UuidUtils.getUUID();
+	private ActionListener listener;
+	public abstract void run();
+	private Map<String, Object> data = null;
+	private TenderProjectEntity parentProject;
+	private TenderProjectEntity tenderProject;
+	private TenderProjectRuleEntity tenderProjectRule;
+	private TenderProjectService tenderProjectService;
+	private ProjectRuleService projectRuleService;
+	private EvaluationStep evaluationStep;
+	
+	private Menu menu;
+	
+	/**
+	 * @Description: 添加action监听
+	 * @author guoyr
+	 * @param listener
+	 */
+	public void addActionListener(ActionListener listener){
+		this.listener = listener;
+	}
+	
+
+	public TenderProjectEntity refreshParentProject() {
+		if(null == tenderProjectService){
+			tenderProjectService = new TenderProjectService();
+		}
+		parentProject = tenderProjectService.getById(parentProject.getId());
+		return parentProject;
+	}
+	
+	public TenderProjectEntity refreshTenderProject() {
+		if(null == tenderProjectService){
+			tenderProjectService = new TenderProjectService();
+		}
+		tenderProject = tenderProjectService.getById(tenderProject.getId());
+		tenderProject.setParentProjectEntity(parentProject);
+		return tenderProject;
+	}
+	
+
+	public TenderProjectRuleEntity refreshTenderProjectRule() {
+		if(null == projectRuleService){
+			projectRuleService = new ProjectRuleService();
+		}
+//		if(null != tenderProjectRule && null != tenderProjectRule.getId()){
+//		}
+		tenderProjectRule = projectRuleService.getProjectRule(tenderProject.getId());
+		if(null == tenderProjectRule) {
+			tenderProjectRule = new TenderProjectRuleEntity();
+			tenderProjectRule.setTenderId(tenderProject.getId());
+			tenderProjectRule.setId(UuidUtils.getUUID());
+			projectRuleService.insert(tenderProjectRule);
+		}
+		return tenderProjectRule;
+	}
+	
+
+	/**
+	 * @Description: 获取action监听
+	 * @author guoyr
+	 * @return
+	 */
+	public ActionListener getListener() {
+		return listener;
+	}
+
+	public Menu getMenu() {
+		return menu;
+	}
+
+	public void setMenu(Menu menu) {
+		this.menu = menu;
+	}
+
+	
+	public TenderProjectEntity getParentProject() {
+		return parentProject;
+	}
+
+	public void setParentProject(TenderProjectEntity parentProject) {
+		this.parentProject = parentProject;
+	}
+
+	public TenderProjectEntity getTenderProject() {
+		return tenderProject;
+	}
+
+	public void setTenderProject(TenderProjectEntity tenderProject) {
+		this.tenderProject = tenderProject;
+		this.tenderProject.setParentProjectEntity(getParentProject());
+	}
+
+	public TenderProjectRuleEntity getTenderProjectRule() {
+		return tenderProjectRule;
+	}
+
+	public void setTenderProjectRule(TenderProjectRuleEntity tenderProjectRule) {
+		this.tenderProjectRule = tenderProjectRule;
+	}
+
+	
+	public EvaluationStep getEvaluationStep() {
+		return evaluationStep;
+	}
+
+
+	public void setEvaluationStep(EvaluationStep evaluationStep) {
+		this.evaluationStep = evaluationStep;
+	}
+
+
+	/**
+	 * @Description: 设置data数据
+	 * @author guoyr
+	 * @param key
+	 * @param value
+	 */
+	public void setData(String key, Object value) {
+		if(data == null){
+			data = new HashMap<String, Object>();
+		}
+		data.put(key, value);
+	}
+
+	public Shell getParentShell(Shell parent){
+		if(null != parent && !parent.isDisposed()){
+			return parent;
+		}else {
+			Shell _parentShell = null;
+			_parentShell = Display.getDefault().getActiveShell();
+			if(null != _parentShell && !_parentShell.isDisposed()){
+				return _parentShell;
+			}else {
+				Shell[] shells = Display.getDefault().getShells();
+				if(null != shells && shells.length > 0){
+					for(int i = shells.length -1; i >= 0; i--){
+						if(null != shells[i] && !shells[i].isDisposed()){
+							return shells[i];
+						}
+					}
+				}
+			}
+		}
+		return new Shell(SWT.ON_TOP);
+	}
+	/**
+	 * @Description: 获取data数据
+	 * @author guoyr
+	 * @param key
+	 * @return
+	 */
+	public Object getData(String key) {
+		if(data != null){
+			return data.get(key);
+		}
+		return null;
+	}
+	@Override
+	public String toString() {
+		return id;
+	}
+	
+}
diff --git a/com.gx.obe.action/src/com/gx/obe/action/bean/CAction.java b/com.gx.obe.action/src/com/gx/obe/action/bean/CAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..e9182ff8e06e16c0b71b2fce1279b9a61ecaec8e
--- /dev/null
+++ b/com.gx.obe.action/src/com/gx/obe/action/bean/CAction.java
@@ -0,0 +1,18 @@
+package com.gx.obe.action.bean;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.action.listener.ActionListener;
+
+public abstract class CAction extends Action {
+	
+	@Override
+	public void run() {
+		ActionListener listener = this.getListener();
+		listener.onLoad(this);
+		listener.loadComposite(this, initComposite(listener.getParentComposite()));
+	}
+	
+	protected abstract Composite initComposite(Composite parent);
+	
+}
diff --git a/com.gx.obe.action/src/com/gx/obe/action/bean/FAction.java b/com.gx.obe.action/src/com/gx/obe/action/bean/FAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..02ea566d3d8e645d543337652391a485d411a5ee
--- /dev/null
+++ b/com.gx.obe.action/src/com/gx/obe/action/bean/FAction.java
@@ -0,0 +1,26 @@
+package com.gx.obe.action.bean;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.action.listener.ActionListener;
+import com.gx.obe.component.rx.RxSwt;
+
+public abstract class FAction<T> extends Action {
+	
+	@Override
+	public void run() {
+		ActionListener listener = this.getListener();
+		listener.onLoad(this);
+		RxSwt.run(this::supply).checkWidget(listener.getParentComposite()).exe(this::loadComposite);
+	}
+	
+	private void loadComposite(T t) {
+		ActionListener listener = this.getListener();
+		listener.loadComposite(this, consume(listener.getParentComposite(), t));
+	}
+	
+	protected abstract T supply();
+	
+	protected abstract Composite consume(Composite parent, T t);
+	
+}
diff --git a/com.gx.obe.action/src/com/gx/obe/action/listener/ActionListener.java b/com.gx.obe.action/src/com/gx/obe/action/listener/ActionListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc435171722983327d7746adfab9f18869207aee
--- /dev/null
+++ b/com.gx.obe.action/src/com/gx/obe/action/listener/ActionListener.java
@@ -0,0 +1,33 @@
+package com.gx.obe.action.listener;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.action.bean.Action;
+
+/**
+ * @Description: 公共的action监听接口
+ * @author guoyr
+ */
+public interface ActionListener{
+
+	/**
+	 * @Description: 重载监听
+	 * @author guoyr
+	 */
+	public void onLoad(Action action); 
+	
+	/**
+	 * @Description: 面板加载监听
+	 * @author guoyr
+	 * @param action
+	 * @param composite
+	 */
+	public void loadComposite(Action action, Composite composite);
+
+	/**
+	 * @Description: 获取父级面板
+	 * @author guoyr
+	 * @return
+	 */
+	public Composite getParentComposite();
+}
diff --git a/com.gx.obe.answer/META-INF/MANIFEST.MF b/com.gx.obe.answer/META-INF/MANIFEST.MF
index bda41e65dedbbeae3e798d198ec27e7354601742..518e0b134f0afea88a465f4207f94ba6f9a57987 100644
--- a/com.gx.obe.answer/META-INF/MANIFEST.MF
+++ b/com.gx.obe.answer/META-INF/MANIFEST.MF
@@ -30,3 +30,5 @@ Export-Package: com.gx.obe.answer,
  com.gx.obe.answer.dataset,
  com.gx.obe.answer.dialog,
  com.gx.obe.answer.thread
+Import-Package: com.gx.obe.action.bean,
+ com.gx.obe.action.utils
diff --git a/com.gx.obe.bind/META-INF/MANIFEST.MF b/com.gx.obe.bind/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..75d32f3f2ca4cb27812d2ea926a1961c43ff7b9b
--- /dev/null
+++ b/com.gx.obe.bind/META-INF/MANIFEST.MF
@@ -0,0 +1,24 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Bind
+Bundle-SymbolicName: com.gx.obe.bind
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: com.gx.obe.bind.Activator
+Bundle-Vendor: GX
+Require-Bundle: org.eclipse.ui,
+  org.eclipse.core.runtime
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: com.gx.obe.bind
+Bundle-ActivationPolicy: lazy
+Export-Package: com.gx.obe.bind,
+ com.gx.obe.bind.base,
+ com.gx.obe.bind.call,
+ com.gx.obe.bind.exception,
+ com.gx.obe.bind.fun,
+ com.gx.obe.bind.promise,
+ com.gx.obe.bind.prop,
+ com.gx.obe.bind.recursion,
+ com.gx.obe.bind.rx,
+ com.gx.obe.bind.stream,
+ com.gx.obe.bind.utils,
+ com.gx.obe.bind.view
diff --git a/com.gx.obe.bind/build.properties b/com.gx.obe.bind/build.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5f4af4c12f2be47c626539ee2608fd76e1a96c77
--- /dev/null
+++ b/com.gx.obe.bind/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
+javacDefaultEncoding.. = UTF-8
\ No newline at end of file
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/Activator.java b/com.gx.obe.bind/src/com/gx/obe/bind/Activator.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2b1a6d1df109d5555e6defccfb41aa63e4be9c8
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/Activator.java
@@ -0,0 +1,50 @@
+package com.gx.obe.bind;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "com.gx.obe.bind"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/base/P.java b/com.gx.obe.bind/src/com/gx/obe/bind/base/P.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d54121dc74ee16492db30d9a719dc7a6cb04bd8
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/base/P.java
@@ -0,0 +1,134 @@
+package com.gx.obe.bind.base;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.Supplier;
+
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.RView;
+import com.gx.obe.bind.view.Write;
+
+public class P<T> implements RView<T> {
+	
+	private boolean log;
+	
+	private T value;
+	
+	private Map<String, BiConsumer<T, T>> writeMap = new HashMap<>();
+	
+	private List<ChangeListener> changeListenerList = new ArrayList<>();
+	
+	private String name;
+	
+	private BiPredicate<T, T> predicate = (o, n) -> true;
+	
+	private T defaultValue;
+	
+	private Supplier<T> other = () -> defaultValue;
+	
+	public P<T> as(String name) {
+		this.name = Objects.requireNonNull(name);
+		this.log = true;
+		return this;
+	}
+	
+	public P<T> orElseGet(Supplier<T> other) {
+		this.other = Objects.requireNonNull(other);
+		this.value = other.get();
+		return this;
+	}
+	
+	public P<T> orElse(T defaultValue) {
+		this.defaultValue = defaultValue;
+		this.value = defaultValue;
+		return this;
+	}
+	
+	public P<T> limit(BiPredicate<T, T> predicate) {
+		this.predicate = Objects.requireNonNull(predicate);
+		return this;
+	}
+	
+	public T get() {
+		return value;
+	}
+	
+	public void bind(Write<T> write) {
+		bind(UUID.randomUUID().toString(), write);
+	}
+	
+	public void bind(String key, Write<T> write) {
+		Objects.requireNonNull(write);
+		this.writeMap.put(key, (o, n) -> write.set(n));
+	}
+	
+	public void watch(BiConsumer<T, T> biConsumer) {
+		watch(UUID.randomUUID().toString(), biConsumer);
+	}
+	
+	public void watch(String key, BiConsumer<T, T> biConsumer) {
+		Objects.requireNonNull(biConsumer);
+		this.writeMap.put(key, biConsumer);
+	}
+	
+	public void bindExe(Write<T> write) {
+		bindExe(UUID.randomUUID().toString(), write);
+	}
+	
+	public void bindExe(String key, Write<T> write) {
+		Objects.requireNonNull(write);
+		write.set(value);
+		this.writeMap.put(key, (o, n) -> write.set(n));
+	}
+	
+	public void clearBind() {
+		this.writeMap.clear();
+		this.value = other.get();
+	}
+	
+	public void clearListener() {
+		this.changeListenerList.clear();
+	}
+	
+	private void _change(T value) {
+		if (log) System.out.println(name + "  --source:" + this.value + "  --change:" + value);
+		this.value = Optional.ofNullable(value).orElseGet(other);
+		this.changeListenerList.forEach(ChangeListener::change);
+	}
+	
+	protected void change(T value) {
+		T old = this.value;
+		if (!predicate.test(old, value)) return;
+		_change(value);
+		this.writeMap.values().stream().forEach(c -> c.accept(old, get()));
+	}
+	
+	protected void change(T value, String key) {
+		T old = this.value;
+		if (!predicate.test(old, value)) return;
+		_change(value);
+		this.writeMap.entrySet().stream().filter(e -> !e.getKey().equals(key)).map(e -> e.getValue()).forEach(c -> c.accept(old, get()));
+	}
+	
+	public boolean isBind() {
+		return !writeMap.isEmpty();
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		this.changeListenerList.add(Objects.requireNonNull(changeListener));
+	}
+	
+	@Override
+	public String toString() {
+		return "P:" + Objects.toString(value);
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/call/Call.java b/com.gx.obe.bind/src/com/gx/obe/bind/call/Call.java
new file mode 100644
index 0000000000000000000000000000000000000000..42d70036ed467727c6f655aa8285d80188e52a5f
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/call/Call.java
@@ -0,0 +1,59 @@
+package com.gx.obe.bind.call;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import com.gx.obe.bind.view.Read;
+import com.gx.obe.bind.view.Write;
+
+public class Call {
+	
+	private final List<Callback> callbackList = new ArrayList<>();
+	
+	public static Call of(Callback callback) {
+		return new Call().bind(callback);
+	}
+	
+	public boolean isBind() {
+		return !callbackList.isEmpty();
+	}
+	
+	public Call bind(Callback callback) {
+		callbackList.add(callback);
+		return this;
+	}
+	
+	public Call bindExe(Callback callback) {
+		callback.call();
+		return bind(callback);
+	}
+	
+	public void exe() {
+		callbackList.stream().forEach(Callback::call);
+	}
+	
+	public <T> Consumer<T> toSet() {
+		return t -> exe();
+	}
+	
+	public <T> Supplier<T> toGet() {
+		return () -> {
+			exe();
+			return null;
+		};
+	}
+	
+	public <T> Write<T> toWrite() {
+		return t -> exe();
+	}
+	
+	public <T> Read<T> toRead() {
+		return () -> {
+			exe();
+			return null;
+		};
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/call/Callback.java b/com.gx.obe.bind/src/com/gx/obe/bind/call/Callback.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a561413969cd691ba88844fda638bdf5c47f949
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/call/Callback.java
@@ -0,0 +1,5 @@
+package com.gx.obe.bind.call;
+
+public interface Callback {
+	void call();
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/exception/ExFunction.java b/com.gx.obe.bind/src/com/gx/obe/bind/exception/ExFunction.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3c80b22917f4d82d8c23eccbcfe2fb4de75b5ca
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/exception/ExFunction.java
@@ -0,0 +1,7 @@
+package com.gx.obe.bind.exception;
+
+public interface ExFunction<T, R> {
+	
+	R apply(T t) throws Exception;
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/exception/ExceptionFun.java b/com.gx.obe.bind/src/com/gx/obe/bind/exception/ExceptionFun.java
new file mode 100644
index 0000000000000000000000000000000000000000..994cdb95103484ec7d8b9587557822cb6f709513
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/exception/ExceptionFun.java
@@ -0,0 +1,46 @@
+package com.gx.obe.bind.exception;
+
+import java.math.BigDecimal;
+import java.util.function.Function;
+
+public class ExceptionFun<T, R> implements Function<T, R> {
+	
+	private ExFunction<T, R> function;
+	
+	public static <T, R> ExceptionFun<T, R> of(ExFunction<T, R> function) {
+		return new ExceptionFun<>(function);
+	}
+	
+	public ExceptionFun(ExFunction<T, R> function) {
+		this.function = function;
+	}
+	
+	public R get(T t) {
+		return getOrDefault(t, null);
+	}
+	
+	public R getOrDefault(T t, R defaultValue) {
+		try {
+			return function.apply(t);
+		} catch (Exception e) {
+			return defaultValue;
+		}
+	}
+	
+	public R getOrThrow(T t) {
+		try {
+			return function.apply(t);
+		} catch (Exception e) {
+			throw new NullPointerException(e.getMessage());
+		}
+	}
+	
+	public static final ExceptionFun<String, BigDecimal> toBigDecimal = of(BigDecimal::new);
+	public static final ExceptionFun<String, Integer> toInteger = of(Integer::valueOf);
+	
+	@Override
+	public R apply(T t) {
+		return get(t);
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/fun/Fun.java b/com.gx.obe.bind/src/com/gx/obe/bind/fun/Fun.java
new file mode 100644
index 0000000000000000000000000000000000000000..5aa16b4643725dd0e3c66ecc173241cf8d3564c7
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/fun/Fun.java
@@ -0,0 +1,63 @@
+package com.gx.obe.bind.fun;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+
+import com.gx.obe.bind.view.Read;
+import com.gx.obe.bind.view.Write;
+
+public class Fun<T, R> {
+	
+	private Function<T, R> function;
+	
+	private Fun(Function<T, R> function) {
+		this.function = function;
+	}
+	
+	public <V> Fun<T, V> andThen(Function<R, V> after) {
+		return Fun.of(function.andThen(after));
+	}
+	
+	public <V> Fun<V, R> compose(Function<V, T> before) {
+		return Fun.of(function.compose(before));
+	}
+	
+	public Function<T, R> toFun() {
+		return function;
+	}
+	
+	public Supplier<R> toGet(T t) {
+		return () -> function.apply(t);
+	}
+	
+	public Supplier<R> toGet(Supplier<T> supplier) {
+		return () -> function.apply(supplier.get());
+	}
+	
+	public Read<R> toRead(T t) {
+		return () -> function.apply(t);
+	}
+	
+	public Read<R> toRead(Read<T> read) {
+		return () -> function.apply(read.get());
+	}
+	
+	public Consumer<T> toSet(Consumer<R> consumer) {
+		return t -> consumer.accept(function.apply(t));
+	}
+	
+	public Write<T> toWrite(Consumer<R> consumer) {
+		return t -> consumer.accept(function.apply(t));
+	}
+	
+	public Predicate<T> toTest(Predicate<R> predicate) {
+		return t -> predicate.test(function.apply(t));
+	}
+	
+	public static <T, R> Fun<T, R> of(Function<T, R> function) {
+		return new Fun<>(function);
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/promise/Promise.java b/com.gx.obe.bind/src/com/gx/obe/bind/promise/Promise.java
new file mode 100644
index 0000000000000000000000000000000000000000..581066436715dbcd26a35be1f037f5f6c6038481
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/promise/Promise.java
@@ -0,0 +1,137 @@
+package com.gx.obe.bind.promise;
+
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+public class Promise<T> {
+	
+	private STATUS status = STATUS.PENDING;
+	
+	private T value;
+	private Exception error;
+	
+	private Consumer<T> onFullFilled = t -> {};
+	private Consumer<Exception> onRejected = e -> {};
+	
+	enum STATUS {
+		PENDING, RESOLVE, REJECT;
+	}
+	
+	public Promise(Fun<T> fun) {
+		Consumer<T> resolve = t -> {
+			this.status = STATUS.RESOLVE;
+			this.value = t;
+			this.onFullFilled.accept(t);
+			synchronized (this) {
+				this.notify();
+			}
+		};
+		Consumer<Exception> reject = e -> {
+			this.status = STATUS.REJECT;
+			this.error = e;
+			this.onRejected.accept(e);
+			synchronized (this) {
+				this.notify();
+			}
+		};
+		try {
+			fun.call(resolve, reject);
+		} catch (Exception e) {
+			reject.accept(e);
+		}
+	}
+	
+	public static <T> Promise<T> thread(Fun<T> fun) {
+		return new Promise<>((resolve, reject) -> {
+			new Thread(() -> {
+				try {
+					fun.call(resolve, reject);
+				} catch (Exception e) {
+					e.printStackTrace();
+					reject.accept(e);
+				}
+			}).start();
+		});
+	}
+	
+	public static <T> Promise<T> empty() {
+		return new Promise<>((resolve, reject) -> {});
+	}
+	
+	public static <T> Promise<T> resolve(T value) {
+		return new Promise<>((resolve, reject) -> resolve.accept(value));
+	}
+	
+	public static <T> Promise<T> reject() {
+		return reject(new RuntimeException("Promise reject error"));
+	}
+	
+	public static <T> Promise<T> reject(Exception err) {
+		return new Promise<>((resolve, reject) -> reject.accept(err));
+	}
+	
+	public static <T, R> Function<T, Promise<R>> resolveFun(Function<T, R> function) {
+		return t -> new Promise<R>((resolve, reject) -> resolve.accept(function.apply(t)));
+	}
+	
+	public <R> Promise<R> then(Function<T, Promise<R>> onFullFilled) {
+		switch (this.status) {
+			case RESOLVE:
+				return onFullFilled.apply(this.value);
+			case REJECT:
+				return new Promise<R>((resolve, reject) -> reject.accept(this.error));
+			default:
+				return new Promise<R>((resolve, reject) -> {
+					this.onFullFilled = t -> onFullFilled.apply(t).then(resolve, reject);
+					this.onRejected = reject;
+				});
+		}
+	}
+	
+	public void then(Consumer<T> onFullFilled, Consumer<Exception> onRejected) {
+		switch (status) {
+			case RESOLVE:
+				if (onFullFilled != null) onFullFilled.accept(value);
+				break;
+			case REJECT:
+				if (onRejected != null) onRejected.accept(error);
+				break;
+			default:
+				if (onFullFilled != null) this.onFullFilled = onFullFilled;
+				if (onRejected != null) this.onRejected = onRejected;
+				break;
+		}
+	}
+	
+	public void thenThrow(Consumer<T> onFullFilled) {
+		then(onFullFilled, e -> {
+			throw new RuntimeException(e.getMessage());
+		});
+	}
+	
+	public T waitOrGet() throws Exception {
+		return waitOrGet(0);
+	}
+	
+	public T waitOrGet(long timeout) throws Exception {
+		switch (status) {
+			case RESOLVE:
+				return value;
+			case REJECT:
+				throw error;
+			default:
+				synchronized (this) {
+					this.wait(timeout);
+				}
+				if (STATUS.PENDING.equals(status)) {
+					throw new RuntimeException();
+				}
+				return waitOrGet(timeout);
+		}
+	}
+	
+	public interface Fun<T> {
+		void call(Consumer<T> resolve, Consumer<Exception> reject);
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/prop/Comp.java b/com.gx.obe.bind/src/com/gx/obe/bind/prop/Comp.java
new file mode 100644
index 0000000000000000000000000000000000000000..c16be4fd504cd3c0551463863d36e3196b847a78
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/prop/Comp.java
@@ -0,0 +1,34 @@
+package com.gx.obe.bind.prop;
+
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import com.gx.obe.bind.view.View;
+import com.gx.obe.bind.view.Write;
+
+public class Comp<T> extends Prop<T> {
+	
+	public Comp(Supplier<T> supplier, String name, View... properties) {
+		super(Objects.requireNonNull(supplier).get());
+		Arrays.stream(Objects.requireNonNull(properties)).forEach(p -> p.addChangeListener(() -> set(supplier.get())));
+	}
+	
+	@Override
+	public Comp<T> as(String name) {
+		super.as(name);
+		return this;
+	}
+	
+	@Override
+	public void bind(Write<T> write) {
+		super.bind(write);
+	}
+	
+	public Comp<T> addSet(Consumer<T> consumer) {
+		super.addChangeListener(() -> consumer.accept(get()));
+		return this;
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/prop/Prop.java b/com.gx.obe.bind/src/com/gx/obe/bind/prop/Prop.java
new file mode 100644
index 0000000000000000000000000000000000000000..6adab503bbb0e4aadcea99ed9ff9802006e1120f
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/prop/Prop.java
@@ -0,0 +1,103 @@
+package com.gx.obe.bind.prop;
+
+import java.util.Objects;
+import java.util.UUID;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import com.gx.obe.bind.base.P;
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.MView;
+import com.gx.obe.bind.view.Read;
+import com.gx.obe.bind.view.View;
+import com.gx.obe.bind.view.Write;
+
+public class Prop<T> extends P<T> implements MView<T> {
+	
+	private Lock lock = new Lock();
+	
+	public Prop() {}
+	
+	public Prop(T value) {
+		set(value);
+	}
+	
+	public Prop<T> orElseGet(Supplier<T> other) {
+		super.orElseGet(other);
+		return this;
+	}
+	
+	public Prop<T> orElse(T defaultValue) {
+		super.orElse(defaultValue);
+		return this;
+	}
+	
+	@Override
+	public Prop<T> as(String name) {
+		super.as(name);
+		return this;
+	}
+	
+	@Override
+	public Prop<T> limit(BiPredicate<T, T> predicate) {
+		super.limit(predicate);
+		return this;
+	}
+	
+	public boolean isLock() {
+		return lock.isLock();
+	}
+	
+	public void replace(Function<T, T> function) {
+		set(Objects.requireNonNull(function).apply(get()));
+	}
+	
+	public void changer(Consumer<T> consumer) {
+		Objects.requireNonNull(consumer).accept(get());
+		set(get());
+	}
+	
+	public void bindBidirectional(MView<T> mView) {
+		Objects.requireNonNull(mView);
+		String key = UUID.randomUUID().toString();
+		bind(key, mView);
+		mView.addChangeListener(() -> set(mView.get(), key));
+	}
+	
+	public void bindBidirectional(Write<T> write, Read<T> read, View model) {
+		Objects.requireNonNull(write);
+		Objects.requireNonNull(read);
+		Objects.requireNonNull(model);
+		
+		String key = UUID.randomUUID().toString();
+		bind(key, write);
+		model.addChangeListener(() -> set(read.get(), key));
+	}
+	
+	@Override
+	public void set(T value) {
+		lock.sync(() -> change(value));
+	}
+	
+	private void set(T value, String key) {
+		lock.sync(() -> change(value, key));
+	}
+	
+}
+
+class Lock {
+	private boolean lock = false;
+	
+	public boolean isLock() {
+		return lock;
+	}
+	
+	public void sync(ChangeListener changeListener) {
+		if (lock) return;
+		lock = true;
+		changeListener.change();
+		lock = false;
+	}
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/prop/RProp.java b/com.gx.obe.bind/src/com/gx/obe/bind/prop/RProp.java
new file mode 100644
index 0000000000000000000000000000000000000000..f0a64f6643958e5d22646e139477d1a814d6d6c1
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/prop/RProp.java
@@ -0,0 +1,34 @@
+package com.gx.obe.bind.prop;
+
+import java.util.Objects;
+import java.util.function.BiPredicate;
+
+import com.gx.obe.bind.base.P;
+import com.gx.obe.bind.view.RView;
+import com.gx.obe.bind.view.Read;
+import com.gx.obe.bind.view.View;
+
+public class RProp<T> extends P<T> {
+	
+	public void reader(Read<? extends T> read, View model) {
+		Objects.requireNonNull(read);
+		Objects.requireNonNull(model);
+		
+		model.addChangeListener(() -> change(read.get()));
+	}
+	
+	public void reader(RView<? extends T> rView) {
+		reader(rView, rView);
+	}
+	
+	public RProp<T> as(String name) {
+		super.as(name);
+		return this;
+	}
+	
+	public RProp<T> limit(BiPredicate<T, T> predicate) {
+		super.limit(predicate);
+		return this;
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/recursion/RStream.java b/com.gx.obe.bind/src/com/gx/obe/bind/recursion/RStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ca61d1b59f021af8162c96d1c0424ef033a9d80
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/recursion/RStream.java
@@ -0,0 +1,21 @@
+package com.gx.obe.bind.recursion;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public interface RStream<T> {
+	
+	void forEach(Consumer<T> action);
+	
+	void forEach(TreeForEach<T> treeForEach);
+	
+	void forEach(BiConsumer<List<Integer>, T> indexConsumer);
+	
+	Optional<T> findAny(Predicate<T> predicate);
+	
+	List<T> filter(Predicate<T> predicate);
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/recursion/Recursions.java b/com.gx.obe.bind/src/com/gx/obe/bind/recursion/Recursions.java
new file mode 100644
index 0000000000000000000000000000000000000000..a2f61bdf180785d5012e951226d194c0d6e58239
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/recursion/Recursions.java
@@ -0,0 +1,167 @@
+package com.gx.obe.bind.recursion;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+public class Recursions<T> {
+	
+	private Function<T, Stream<T>> toStreamFun;
+	
+	public static <T> Recursions<T> array(Function<T, T[]> toArrayFun) {
+		return new Recursions<>(toArrayFun.andThen(t -> Optional.ofNullable(t).map(Stream::of).orElse(null)));
+	}
+	
+	public static <T> Recursions<T> list(Function<T, List<T>> toListFun) {
+		return new Recursions<>(toListFun.andThen(t -> Optional.ofNullable(t).map(List::stream).orElse(null)));
+	}
+	
+	public static <T> Recursions<T> stream(Function<T, Stream<T>> toStreamFun) {
+		return new Recursions<>(toStreamFun);
+	}
+	
+	public Recursions(Function<T, Stream<T>> toStreamFun) {
+		this.toStreamFun = toStreamFun;
+	}
+	
+	public RStream<T> toStream(T obj) {
+		return toStream(Stream.of(obj));
+	}
+	
+	public RStream<T> toStream(T[] array) {
+		return toStream(Stream.of(array));
+	}
+	
+	public RStream<T> toStream(List<T> stream) {
+		return toStream(stream.stream());
+	}
+	
+	public RStream<T> toStream(Stream<T> stream) {
+		return new RStream<T>() {
+			
+			public void forEach(Consumer<T> action) {
+				new ForEachRecursion(action).exe(stream);
+			}
+			
+			public void forEach(TreeForEach<T> treeForEach) {
+				new TreeForEachRecursion(treeForEach).exe(stream);
+			}
+			
+			public void forEach(BiConsumer<List<Integer>, T> indexConsumer) {
+				new IndexForEachRecursion(indexConsumer).exe(stream);
+			}
+			
+			public Optional<T> findAny(Predicate<T> predicate) {
+				Data data = new Data();
+				new AnyMatchRecursion(t -> {
+					boolean test = predicate.test(t);
+					if (test) data.t = t;
+					return test;
+				}).exe(stream);
+				return Optional.ofNullable(data.t);
+			}
+			
+			public List<T> filter(Predicate<T> predicate) {
+				List<T> list = new ArrayList<>();
+				new ForEachRecursion(t -> {
+					if (predicate.test(t)) list.add(t);
+				}).exe(stream);
+				return list;
+			}
+			
+		};
+	}
+	
+	private class AnyMatchRecursion {
+		
+		private Predicate<T> predicate;
+		
+		public AnyMatchRecursion(Predicate<T> predicate) {
+			this.predicate = predicate;
+		}
+		
+		private boolean exe(Stream<T> stream) {
+			return stream.anyMatch(t -> {
+				if (predicate.test(t)) return true;
+				return Optional.ofNullable(t).map(toStreamFun).map(this::exe).orElse(false);
+			});
+		}
+		
+	}
+	
+	private class ForEachRecursion {
+		
+		private Consumer<T> consumer;
+		
+		public ForEachRecursion(Consumer<T> consumer) {
+			this.consumer = consumer;
+		}
+		
+		private void exe(Stream<T> stream) {
+			stream.forEach(t -> {
+				consumer.accept(t);
+				Optional.ofNullable(t).map(toStreamFun).ifPresent(this::exe);
+			});
+		}
+		
+	}
+	
+	private class TreeForEachRecursion {
+		
+		private TreeForEach<T> treeForEach;
+		
+		public TreeForEachRecursion(TreeForEach<T> treeForEach) {
+			this.treeForEach = treeForEach;
+		}
+		
+		private void exe(Stream<T> stream) {
+			recursion(stream.iterator(), true);
+		}
+		
+		private void recursion(Iterator<T> iterator, boolean root) {
+			iterator.forEachRemaining(t -> {
+				Iterator<T> citerator = Optional.of(t).map(toStreamFun).map(Stream::iterator).orElse(null);
+				boolean leaf = citerator == null || !citerator.hasNext();
+				treeForEach.action(root, leaf, t);
+				if (!leaf) recursion(citerator, false);
+			});
+		}
+		
+	}
+	
+	private class IndexForEachRecursion {
+		
+		private BiConsumer<List<Integer>, T> indexConsumer;
+		
+		public IndexForEachRecursion(BiConsumer<List<Integer>, T> indexConsumer) {
+			this.indexConsumer = indexConsumer;
+		}
+		
+		private void exe(Stream<T> stream) {
+			recursion(stream, new ArrayList<>());
+		}
+		
+		private void recursion(Stream<T> stream, List<Integer> pIndex) {
+			AtomicInteger i = new AtomicInteger(1);
+			stream.forEach(t -> {
+				List<Integer> index = new ArrayList<>(pIndex);
+				index.add(i.getAndIncrement());
+				indexConsumer.accept(index, t);
+				Optional.ofNullable(t).map(toStreamFun).ifPresent(s -> recursion(s, index));
+			});
+		}
+		
+	}
+	
+	private class Data {
+		private T t;
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/recursion/TreeForEach.java b/com.gx.obe.bind/src/com/gx/obe/bind/recursion/TreeForEach.java
new file mode 100644
index 0000000000000000000000000000000000000000..0bb321721771e3b5a63172d2c43cdd87d49e6ce8
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/recursion/TreeForEach.java
@@ -0,0 +1,7 @@
+package com.gx.obe.bind.recursion;
+
+public interface TreeForEach<T> {
+	
+	void action(boolean root, boolean leaf, T t);
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/rx/RxBind.java b/com.gx.obe.bind/src/com/gx/obe/bind/rx/RxBind.java
new file mode 100644
index 0000000000000000000000000000000000000000..214767b766fe1d37569054971c78ba56b448bb35
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/rx/RxBind.java
@@ -0,0 +1,80 @@
+package com.gx.obe.bind.rx;
+
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+public class RxBind<T> {
+	
+	private Supplier<T> supplier = () -> null;
+	private Consumer<Runnable> supplierSync = Runnable::run;
+	private Consumer<Runnable> consumerSync = Runnable::run;
+	private Supplier<Boolean> check = () -> true;
+	private Supplier<T> other = () -> null;
+	private Tangent tangent = Tangent.TEMP;
+	
+	public RxBind(Supplier<T> supplier) {
+		this.supplier = supplier;
+	}
+	
+	public static <T> RxBind<T> run(Supplier<T> supplier) {
+		return new RxBind<T>(supplier);
+	}
+	
+	public RxBind<T> tangent(Tangent tangent) {
+		this.tangent = tangent;
+		return this;
+	}
+	
+	public RxBind<T> supplierSync(Consumer<Runnable> supplierSync) {
+		this.supplierSync = supplierSync;
+		return this;
+	}
+	
+	public RxBind<T> consumerSync(Consumer<Runnable> consumerSync) {
+		this.consumerSync = consumerSync;
+		return this;
+	}
+	
+	public RxBind<T> check(Supplier<Boolean> check) {
+		this.check = check;
+		return this;
+	}
+	
+	public RxBind<T> other(Supplier<T> other) {
+		this.other = other;
+		return this;
+	}
+	
+	public void exe(Consumer<T> consumer) {
+		supplierSync.accept(() -> {
+			Status<T> supplyStatus = supplyStatus();
+			consumerSync.accept(() -> {
+				if (check.get()) return;
+				if (supplyStatus.isErrer()) {
+					tangent.error(supplyStatus.getException());
+				} else {
+					tangent.after();
+					try {
+						consumer.accept(Optional.ofNullable(supplyStatus.getT()).orElseGet(other));
+					} catch (Exception e) {
+						e.printStackTrace();
+					}
+				}
+			});
+		});
+		tangent.before();
+	}
+	
+	public Status<T> supplyStatus() {
+		Status<T> status = new Status<>();
+		try {
+			status.setT(supplier.get());
+		} catch (Exception e) {
+			status.setErrer(true);
+			status.setException(e);
+		}
+		return status;
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/rx/Status.java b/com.gx.obe.bind/src/com/gx/obe/bind/rx/Status.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc3edefcfe9898bb9bc61af9dcced8f8f6142bf2
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/rx/Status.java
@@ -0,0 +1,35 @@
+package com.gx.obe.bind.rx;
+
+public class Status<T> {
+	
+	private Exception exception;
+	
+	private T t;
+	
+	private boolean errer;
+	
+	public Exception getException() {
+		return exception;
+	}
+	
+	public void setException(Exception exception) {
+		this.exception = exception;
+	}
+	
+	public T getT() {
+		return t;
+	}
+	
+	public void setT(T t) {
+		this.t = t;
+	}
+	
+	public boolean isErrer() {
+		return errer;
+	}
+	
+	public void setErrer(boolean errer) {
+		this.errer = errer;
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/rx/Tangent.java b/com.gx.obe.bind/src/com/gx/obe/bind/rx/Tangent.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3b05a8bc0a4c526b813caf96cdd7085d16da48d
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/rx/Tangent.java
@@ -0,0 +1,21 @@
+package com.gx.obe.bind.rx;
+
+public interface Tangent {
+	
+	static Tangent TEMP = new Tangent() {
+		public void error(Exception e) {
+			e.printStackTrace();
+		}
+		
+		public void before() {}
+		
+		public void after() {}
+	};
+	
+	void before();
+	
+	void after();
+	
+	void error(Exception e);
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/stream/MapStream.java b/com.gx.obe.bind/src/com/gx/obe/bind/stream/MapStream.java
new file mode 100644
index 0000000000000000000000000000000000000000..dae1bce7f784e0072c4d1e4ba5abf6db1c3546c1
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/stream/MapStream.java
@@ -0,0 +1,59 @@
+package com.gx.obe.bind.stream;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+public class MapStream<K, V> {
+	
+	private Map<K, V> map;
+	
+	public MapStream(Map<K, V> map) {
+		this.map = map;
+	}
+	
+	public static <K, V> MapStream<K, V> of(Map<K, V> map) {
+		return new MapStream<>(map);
+	}
+	
+	public <T> MapStream<K, T> valueMap(Function<V, T> function) {
+		Map<K, T> map = new HashMap<>();
+		this.map.forEach((k, v) -> map.put(k, function.apply(v)));
+		return MapStream.of(map);
+	}
+	
+	public <T> void valueMap(Function<V, T> function, Map<K, T> map) {
+		this.map.forEach((k, v) -> map.put(k, function.apply(v)));
+	}
+	
+	public MapStream<K, V> removeValueIsNull() {
+		Map<K, V> map = new HashMap<>();
+		this.map.forEach((k, v) -> {
+			if (v != null) map.put(k, v);
+		});
+		return MapStream.of(map);
+	}
+	public MapStream<K, V> removeValue(Predicate<V> predicate) {
+		Map<K, V> map = new HashMap<>();
+		this.map.forEach((k, v) -> {
+			if (!predicate.test(v)) map.put(k, v);
+		});
+		return MapStream.of(map);
+	}
+	
+	public Stream<K> keyStream(Predicate<V> vPredicate) {
+		return map.entrySet().stream().filter(e -> vPredicate.test(e.getValue())).map(e -> e.getKey());
+	}
+	
+	public Map<K, V> toMap() {
+		return map;
+	}
+	
+	public void forEach(BiConsumer<K, V> action) {
+		map.forEach(action);
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/utils/CollectorUtils.java b/com.gx.obe.bind/src/com/gx/obe/bind/utils/CollectorUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..4463c334c21e38838b632cfe38bce679e6028799
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/utils/CollectorUtils.java
@@ -0,0 +1,14 @@
+package com.gx.obe.bind.utils;
+
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+public class CollectorUtils {
+	
+	public static <T, K1, K2> Collector<T, ?, Map<K1, Map<K2, T>>> groupingToMap(Function<? super T, ? extends K1> classifier, Function<? super T, ? extends K2> keyMapper) {
+		return Collectors.groupingBy(classifier, Collectors.toMap(keyMapper, Function.identity()));
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/utils/PropUtils.java b/com.gx.obe.bind/src/com/gx/obe/bind/utils/PropUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..a11601e3f9da598698a058dbbfb6bf9cd5dafada
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/utils/PropUtils.java
@@ -0,0 +1,20 @@
+package com.gx.obe.bind.utils;
+
+import java.util.function.Function;
+
+import com.gx.obe.bind.prop.Prop;
+
+public class PropUtils {
+	
+	public static <T, R> void bindBidirectional(Prop<T> tProp, Prop<R> rProp, Function<T, R> trFunction, Function<R, T> rtFunction) {
+		tProp.addChangeListener(() -> {
+			if (rProp.isLock()) return;
+			rProp.set(trFunction.apply(tProp.get()));
+		});
+		rProp.addChangeListener(() -> {
+			if (tProp.isLock()) return;
+			tProp.set(rtFunction.apply(rProp.get()));
+		});
+	}
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/view/ChangeListener.java b/com.gx.obe.bind/src/com/gx/obe/bind/view/ChangeListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f5cbcaeecdf6237c8f385f3461f8e709259f930
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/view/ChangeListener.java
@@ -0,0 +1,15 @@
+package com.gx.obe.bind.view;
+
+public interface ChangeListener {
+	
+	void change();
+	
+	default ChangeListener andThen(ChangeListener changeListener) {
+		return () -> {
+			this.change();
+			changeListener.change();
+		};
+	}
+	
+	static ChangeListener EMPTY = () -> {};
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/view/MView.java b/com.gx.obe.bind/src/com/gx/obe/bind/view/MView.java
new file mode 100644
index 0000000000000000000000000000000000000000..f4b036fd9cf286c8d1c7d7675da89745466acae8
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/view/MView.java
@@ -0,0 +1,3 @@
+package com.gx.obe.bind.view;
+
+public interface MView<T> extends RView<T>, Write<T> {}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/view/RView.java b/com.gx.obe.bind/src/com/gx/obe/bind/view/RView.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c1fbc4bb5304718c2593fb01850706f8811f08d
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/view/RView.java
@@ -0,0 +1,3 @@
+package com.gx.obe.bind.view;
+
+public interface RView<T> extends View, Read<T> {}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/view/Read.java b/com.gx.obe.bind/src/com/gx/obe/bind/view/Read.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca4ee6cef4bcdd02b6f6ac79fffb16f5054fed63
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/view/Read.java
@@ -0,0 +1,8 @@
+package com.gx.obe.bind.view;
+
+@FunctionalInterface
+public interface Read<T> {
+	
+	T get();
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/view/View.java b/com.gx.obe.bind/src/com/gx/obe/bind/view/View.java
new file mode 100644
index 0000000000000000000000000000000000000000..e249f6f50440c3d359fb97a8dd01cf4e8bfbd983
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/view/View.java
@@ -0,0 +1,8 @@
+package com.gx.obe.bind.view;
+
+@FunctionalInterface
+public interface View {
+	
+	void addChangeListener(ChangeListener changeListener);
+	
+}
diff --git a/com.gx.obe.bind/src/com/gx/obe/bind/view/Write.java b/com.gx.obe.bind/src/com/gx/obe/bind/view/Write.java
new file mode 100644
index 0000000000000000000000000000000000000000..3fdc89ea321a02ed488f5e349c9820593a56050b
--- /dev/null
+++ b/com.gx.obe.bind/src/com/gx/obe/bind/view/Write.java
@@ -0,0 +1,8 @@
+package com.gx.obe.bind.view;
+
+@FunctionalInterface
+public interface Write<T> {
+	
+	void set(T t);
+	
+}
diff --git a/com.gx.obe.common.widget/src/com/gx/obe/common/widget/shell/ProgressMessageDialog.java b/com.gx.obe.common.widget/src/com/gx/obe/common/widget/shell/ProgressMessageDialog.java
index 7516d21ebf290ac2d905d6f512255d5bbd961ac2..4e3c5654a9a5c398472e05637692b1e010c7428e 100644
--- a/com.gx.obe.common.widget/src/com/gx/obe/common/widget/shell/ProgressMessageDialog.java
+++ b/com.gx.obe.common.widget/src/com/gx/obe/common/widget/shell/ProgressMessageDialog.java
@@ -536,6 +536,10 @@ public class ProgressMessageDialog extends Shell implements ProgressMessageListe
 	public boolean getFinishFlag() {
 		return finishFlag;
 	}
+	
+	public int getErrorMessagesSize() {
+		return errorMessages;
+	}
 
 	
 }
diff --git a/com.gx.obe.component/META-INF/MANIFEST.MF b/com.gx.obe.component/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..871ab47c9c1293a2e2f9270ebeefce5f78d19098
--- /dev/null
+++ b/com.gx.obe.component/META-INF/MANIFEST.MF
@@ -0,0 +1,29 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Component
+Bundle-SymbolicName: com.gx.obe.component
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: com.gx.obe.component.Activator
+Bundle-Vendor: GX
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.swt.core,
+ com.gx.obe.bind,
+ com.gx.obe.utils,
+ com.gx.obe.components.core
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: com.gx.obe.component
+Bundle-ActivationPolicy: lazy
+Export-Package: com.gx.obe.component.comparison,
+ com.gx.obe.component.form,
+ com.gx.obe.component.grid,
+ com.gx.obe.component.handler,
+ com.gx.obe.component.listener,
+ com.gx.obe.component.menu,
+ com.gx.obe.component.rx,
+ com.gx.obe.component.tabfolder,
+ com.gx.obe.component.table,
+ com.gx.obe.component.text,
+ com.gx.obe.component.tree,
+ com.gx.obe.component.utils,
+ com.gx.obe.component.verify
diff --git a/com.gx.obe.component/build.properties b/com.gx.obe.component/build.properties
new file mode 100644
index 0000000000000000000000000000000000000000..5f4af4c12f2be47c626539ee2608fd76e1a96c77
--- /dev/null
+++ b/com.gx.obe.component/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
+javacDefaultEncoding.. = UTF-8
\ No newline at end of file
diff --git a/com.gx.obe.component/src/com/gx/obe/component/Activator.java b/com.gx.obe.component/src/com/gx/obe/component/Activator.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f7e674fbea2a614f3612e4d457723a3f2129616
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/Activator.java
@@ -0,0 +1,50 @@
+package com.gx.obe.component;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "com.gx.obe.component"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/comparison/Column.java b/com.gx.obe.component/src/com/gx/obe/component/comparison/Column.java
new file mode 100644
index 0000000000000000000000000000000000000000..b56d4e541441e90edcb93f0b04b2adea8f9a5acc
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/comparison/Column.java
@@ -0,0 +1,23 @@
+package com.gx.obe.component.comparison;
+
+public class Column {
+	
+	private String id;
+	
+	private String name;
+	
+	public Column(String id, String name) {
+		super();
+		this.id = id;
+		this.name = name;
+	}
+	
+	public String getId() {
+		return id;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/comparison/ComparisonData.java b/com.gx.obe.component/src/com/gx/obe/component/comparison/ComparisonData.java
new file mode 100644
index 0000000000000000000000000000000000000000..8479879f9a50e5344026ec428c555ef2227f9cfd
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/comparison/ComparisonData.java
@@ -0,0 +1,68 @@
+package com.gx.obe.component.comparison;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.util.utils.Keys;
+
+public class ComparisonData {
+	
+	private List<Column> headColList = new ArrayList<>();
+	private List<Column> titleColList = new ArrayList<>();
+	private List<Column> itemColList = new ArrayList<>();
+	private List<String> rowList = new ArrayList<>();
+	
+	private Map<Keys, String> headContentMap = new HashMap<>();
+	private Map<Keys, String> comparisonContentMap = new HashMap<>();
+	
+	public boolean addHeadCol(Column col) {
+		return headColList.add(col);
+	}
+	
+	public boolean addTitleCol(Column col) {
+		return titleColList.add(col);
+	}
+	
+	public boolean addItemCol(Column col) {
+		return itemColList.add(col);
+	}
+	
+	public boolean addRow(String row) {
+		return rowList.add(row);
+	}
+	
+	public String putHeadContent(String rowId, String headId, String value) {
+		return headContentMap.put(Keys.of(rowId, headId), value);
+	}
+	
+	public String putComparisonContent(String rowId, String titleId, String itemId, String value) {
+		return comparisonContentMap.put(Keys.of(rowId, titleId, itemId), value);
+	}
+	
+	public List<Column> getHeadColList() {
+		return headColList;
+	}
+	
+	public List<Column> getTitleColList() {
+		return titleColList;
+	}
+	
+	public List<Column> getItemColList() {
+		return itemColList;
+	}
+	
+	public List<String> getRowList() {
+		return rowList;
+	}
+	
+	public Map<Keys, String> getHeadContentMap() {
+		return headContentMap;
+	}
+	
+	public Map<Keys, String> getComparisonContentMap() {
+		return comparisonContentMap;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/comparison/ComparisonTable.java b/com.gx.obe.component/src/com/gx/obe/component/comparison/ComparisonTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..8687e2f1d346ca51daf40bf5ba2b76422af23803
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/comparison/ComparisonTable.java
@@ -0,0 +1,124 @@
+package com.gx.obe.component.comparison;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.IntStream;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.util.utils.Keys;
+
+import de.kupzog.ktable.KTable;
+import de.kupzog.ktable.KTableCellRenderer;
+import de.kupzog.ktable.SWTX;
+import de.kupzog.ktable.model.CommonKtableCModel;
+import de.kupzog.ktable.renderers.FixedWrapCellRenderer;
+import de.kupzog.ktable.renderers.TextWrapCellRenderer;
+
+public class ComparisonTable extends KTable {
+	
+	/**
+	 * @Description: 换行文本渲染
+	 */
+	private static final FixedWrapCellRenderer FIXED_RENDERER = new FixedWrapCellRenderer();
+	/**
+	 * @Description: 换行文本渲染
+	 */
+	private static final TextWrapCellRenderer TEXT_RENDERER = new TextWrapCellRenderer();
+	
+	/**
+	 * @Description: 固定行数
+	 */
+	private static final int HEAD_ROW = 2;
+	
+	private final CommonKtableCModel model;
+	
+	private final List<Column> headColList;
+	private final List<Column> titleColList;
+	private final List<Column> itemColList;
+	private final List<String> rowList;
+	
+	private final Map<Keys, String> headContentMap;
+	private final Map<Keys, String> comparisonContentMap;
+	
+	public ComparisonTable(Composite parent, ComparisonData comparisonData) {
+		super(parent, SWTX.AUTO_SCROLL | SWT.FULL_SELECTION | SWTX.EDIT_ON_KEY | SWTX.FILL_WITH_LASTCOL);
+		
+		comparisonData = Optional.ofNullable(comparisonData).orElseGet(ComparisonData::new);
+		
+		this.headColList = comparisonData.getHeadColList();
+		this.titleColList = comparisonData.getTitleColList();
+		this.itemColList = comparisonData.getItemColList();
+		this.rowList = comparisonData.getRowList();
+		
+		this.headContentMap = comparisonData.getHeadContentMap();
+		this.comparisonContentMap = comparisonData.getComparisonContentMap();
+		
+		this.model = new CommonKtableCModel(this, HEAD_ROW, headColList.size(), this.rowList.size(), titleColList.size() * itemColList.size());
+		this.setModel(model);
+		
+		IntStream.range(0, headColList.size()).forEach(i -> model.addRowSpan(0, i, HEAD_ROW));
+		IntStream.range(0, titleColList.size()).map(i -> i * itemColList.size()).map(i -> i + headColList.size()).forEach(i -> model.addColSpan(0, i, itemColList.size()));
+		
+		IntStream.range(0, titleColList.size() * itemColList.size( )+ headColList.size()).forEach(i -> model.setColumnWidth(i, 100));
+		
+		this.model.setRowHeightRender($ -> 30);
+//		this.model.setCellBackgroundRender(($, $$) -> SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		
+		this.model.setCellContentRender(this::receiveContent);
+		this.model.setCellRender(this::receiveCellRender);
+		this.model.setCellAlignmentRender(this::receiveCellAlignment);
+	}
+	
+	/**
+	 * @Description: 加载内容
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private String receiveContent(int row, int col) {
+		if (col < headColList.size()) {
+			if (row == 0) return Optional.of(headColList.get(col)).map(Column::getName).orElse("");
+			if (row == 1) return "";
+			return Optional.of(Keys.of(rowList.get(row - 2), headColList.get(col).getId())).map(headContentMap::get).orElse("");
+		}
+		col -= headColList.size();
+		int itemSize = itemColList.size();
+		if (row == 0) return Optional.of(titleColList.get(col / itemSize)).map(Column::getName).orElse("");
+		if (row == 1) return Optional.of(itemColList.get(col % itemSize)).map(Column::getName).orElse("");
+		try {
+			return Optional.of(Keys.of(rowList.get(row - 2), titleColList.get(col / itemSize).getId(), itemColList.get(col % itemSize).getId())).map(comparisonContentMap::get).orElse("");
+		} catch (Exception e) {
+			return "";
+		}
+	}
+	
+	/**
+	 * @Description: 加载渲染器
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private KTableCellRenderer receiveCellRender(int row, int col) {
+		if (this.model.isFixedCell(col, row)) {
+			return FIXED_RENDERER;
+		}
+		return TEXT_RENDERER;
+	}
+	
+	/**
+	 * @Description: 加载单元格对齐方式
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private int receiveCellAlignment(int row, int col) {
+		return SWTX.ALIGN_VERTICAL_CENTER | SWTX.ALIGN_HORIZONTAL_CENTER;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/form/FForm.java b/com.gx.obe.component/src/com/gx/obe/component/form/FForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..2561ec910ad9a2b05c096f2896b8a3503a2289a9
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/form/FForm.java
@@ -0,0 +1,134 @@
+package com.gx.obe.component.form;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.wb.swt.SWTResourceManager;
+
+public class FForm<T> extends Composite {
+	
+	private final IForm<T> iForm;
+	
+	private final List<Consumer<T>> consumerList = new ArrayList<>();
+
+	private int numColumns;
+	
+	public FForm(Composite parent, int numColumns) {
+		super(parent, SWT.NONE);
+		this.numColumns = numColumns;
+		
+		setBackground(SWTResourceManager.getColor(215, 215, 215));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		GridLayout gridLayout = new GridLayout(numColumns * 2, false);
+		gridLayout.verticalSpacing = 1;
+		gridLayout.horizontalSpacing = 1;
+		gridLayout.marginHeight = 1;
+		gridLayout.marginWidth = 1;
+		setLayout(gridLayout);
+		
+		iForm = new IForm<T>() {
+			
+			@Override
+			public void addNull() {
+				CLabel lblNewLabel = new CLabel(FForm.this, SWT.RIGHT);
+				lblNewLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_lblNewLabel = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+				gd_lblNewLabel.heightHint = 30;
+				gd_lblNewLabel.widthHint = 100;
+				lblNewLabel.setLayoutData(gd_lblNewLabel);
+				
+				CLabel lblNewLabel_1 = new CLabel(FForm.this, SWT.NONE);
+				lblNewLabel_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_lblNewLabel_1 = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+				gd_lblNewLabel_1.heightHint = 30;
+				gd_lblNewLabel_1.widthHint = 200;
+				lblNewLabel_1.setLayoutData(gd_lblNewLabel_1);
+			}
+			
+			public void add(String title, Function<T, String> getValueFun) {
+				CLabel lblNewLabel = new CLabel(FForm.this, SWT.RIGHT);
+				lblNewLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_lblNewLabel = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+				gd_lblNewLabel.heightHint = 30;
+				gd_lblNewLabel.widthHint = 100;
+				lblNewLabel.setLayoutData(gd_lblNewLabel);
+				lblNewLabel.setText(title);
+				
+				CLabel lblNewLabel_1 = new CLabel(FForm.this, SWT.NONE);
+				lblNewLabel_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_lblNewLabel_1 = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+				gd_lblNewLabel_1.heightHint = 30;
+				gd_lblNewLabel_1.widthHint = 200;
+				lblNewLabel_1.setLayoutData(gd_lblNewLabel_1);
+				consumerList.add(t -> lblNewLabel_1.setText(Optional.ofNullable(t).map(getValueFun).orElse("")));
+			}
+			
+			public void addLong(String title, Function<T, String> getValueFun) {
+				CLabel lblNewLabel = new CLabel(FForm.this, SWT.RIGHT);
+				lblNewLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_lblNewLabel = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
+				gd_lblNewLabel.heightHint = 30;
+				lblNewLabel.setLayoutData(gd_lblNewLabel);
+				lblNewLabel.setText(title);
+				
+				CLabel lblNewLabel_1 = new CLabel(FForm.this, SWT.NONE);
+				lblNewLabel_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_lblNewLabel_1 = new GridData(SWT.FILL, SWT.CENTER, true, false, numColumns * 2 - 1, 1);
+				gd_lblNewLabel_1.heightHint = 30;
+				lblNewLabel_1.setLayoutData(gd_lblNewLabel_1);
+				consumerList.add(t -> lblNewLabel_1.setText(Optional.ofNullable(t).map(getValueFun).orElse("")));
+			}
+			
+			public void addBig(String title, Function<T, String> getValueFun, int height) {
+				CLabel lblNewLabel = new CLabel(FForm.this, SWT.RIGHT);
+				lblNewLabel.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_lblNewLabel = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
+				gd_lblNewLabel.heightHint = height;
+				lblNewLabel.setLayoutData(gd_lblNewLabel);
+				lblNewLabel.setText(title);
+				
+				Composite composite = new Composite(FForm.this, SWT.NONE);
+				composite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+				GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, false, numColumns * 2 - 1, 1);
+				gd_composite.heightHint = height;
+				composite.setLayoutData(gd_composite);
+				GridLayout gl_composite = new GridLayout(1, false);
+				gl_composite.marginWidth = 1;
+				composite.setLayout(gl_composite);
+				
+				Text lblNewLabel_1 = new Text(composite, SWT.WRAP | SWT.V_SCROLL);
+				lblNewLabel_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+				lblNewLabel_1.setEditable(false);
+				consumerList.add(t -> lblNewLabel_1.setText(Optional.ofNullable(t).map(getValueFun).orElse("")));
+			}
+
+		};
+		
+	}
+	
+	public void init(Consumer<IForm<T>> consumer) {
+		consumer.accept(iForm);	
+		Composite composite_1 = new Composite(this, SWT.NONE);
+		GridData gd_lblNewLabel = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1);
+		gd_lblNewLabel.heightHint = 0;
+		composite_1.setLayoutData(gd_lblNewLabel);
+		composite_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, numColumns * 2, 1));
+	}
+	
+	public void refresh(T t) {
+		consumerList.forEach(c -> c.accept(t));
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/form/IForm.java b/com.gx.obe.component/src/com/gx/obe/component/form/IForm.java
new file mode 100644
index 0000000000000000000000000000000000000000..cf321764c0ffbc5f6d85b28021df40487fd83a8c
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/form/IForm.java
@@ -0,0 +1,19 @@
+package com.gx.obe.component.form;
+
+import java.util.function.Function;
+
+public interface IForm<T> {
+	
+	void addNull();
+	
+	void add(String title, Function<T, String> getValueFun);
+	
+	void addLong(String title, Function<T, String> getValueFun);
+	
+	void addBig(String title, Function<T, String> getValueFun, int height);
+	
+	default void addBig(String title, Function<T, String> getValueFun) {
+		addBig(title, getValueFun, 95);
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.component/src/com/gx/obe/component/grid/FGrid.java b/com.gx.obe.component/src/com/gx/obe/component/grid/FGrid.java
new file mode 100644
index 0000000000000000000000000000000000000000..ebcde67c840b74a93edf1d2c82482f9f5f90a452
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/grid/FGrid.java
@@ -0,0 +1,92 @@
+package com.gx.obe.component.grid;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+
+import org.eclipse.nebula.widgets.grid.Grid;
+import org.eclipse.nebula.widgets.grid.GridColumn;
+import org.eclipse.nebula.widgets.grid.GridItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.RView;
+
+public class FGrid<T> extends Grid implements RView<T> {
+	
+	private final List<Column<T>> columnList = new ArrayList<>();
+	
+	private final List<ChangeListener> changeListeners = new ArrayList<>();
+	
+	private T t;
+	
+	@SuppressWarnings("unchecked")
+	public FGrid(Composite parent) {
+		super(parent, SWT.H_SCROLL | SWT.V_SCROLL);
+		this.setHeaderVisible(true);
+		this.setItemHeight(30);
+		this.addSelectionListener(org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter(e -> {
+			GridItem gridItem = (GridItem) e.item;
+			t = (T) gridItem.getData();
+			changeListeners.forEach(ChangeListener::change);
+		}));
+	}
+	
+	public GridColumn addIndexColumn(String name) {
+		columnList.add(new IndexColumn<>());
+		GridColumn gridColumn = new GridColumn(this, SWT.CENTER);
+		gridColumn.setText(name);
+		return gridColumn;
+	}
+	
+	public GridColumn addColumn(String name, Function<T, String> function, int style) {
+		columnList.add(new Column<>(function));
+		GridColumn gridColumn = new GridColumn(this, style);
+		gridColumn.setText(name);
+		return gridColumn;
+	}
+	
+	public void refresh(List<T> tList) {
+		this.removeAll();
+		if (tList != null) for (int i = 0; i < tList.size(); i++) {
+			T t = tList.get(i);
+			GridItem gridItem = new GridItem(this, SWT.NONE);
+			gridItem.setData(t);
+			for (int j = 0; j < columnList.size(); j++) {
+				Column<T> column = columnList.get(j);
+				if (column instanceof IndexColumn) {
+					gridItem.setText(j, i + 1 + "");
+				} else {
+					gridItem.setText(j, Optional.ofNullable(column.function.apply(t)).orElse(""));
+				}
+			}
+		}
+	}
+	
+	private static class Column<T> {
+		private Function<T, String> function;
+		
+		private Column(Function<T, String> function) {
+			this.function = function;
+		}
+	}
+	
+	private static class IndexColumn<T> extends Column<T> {
+		private IndexColumn() {
+			super(null);
+		}
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		this.changeListeners.add(changeListener);
+	}
+	
+	@Override
+	public T get() {
+		return t;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/handler/ISelection.java b/com.gx.obe.component/src/com/gx/obe/component/handler/ISelection.java
new file mode 100644
index 0000000000000000000000000000000000000000..31e951ef16181aee0be64ecfaa89e4913d166e00
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/handler/ISelection.java
@@ -0,0 +1,22 @@
+package com.gx.obe.component.handler;
+
+import org.eclipse.swt.events.MouseListener;
+
+public interface ISelection {
+	
+	ISelection selection = new ISelection() {
+		
+		public void setText(String text) {}
+		
+		public void setSelection(boolean selection) {}
+		
+		public void addMouseListener(MouseListener mouseUpAdapter) {}
+	};
+	
+	void setText(String text);
+	
+	void addMouseListener(MouseListener mouseUpAdapter);
+	
+	void setSelection(boolean selection);
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/handler/RaidoHandler.java b/com.gx.obe.component/src/com/gx/obe/component/handler/RaidoHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..560ad3102e0fb6da4bf23dd60f877ee2defea861
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/handler/RaidoHandler.java
@@ -0,0 +1,74 @@
+package com.gx.obe.component.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.MView;
+import com.gx.obe.component.utils.CompositeUtils;
+
+public class RaidoHandler<T extends ISelection, R> implements MView<R> {
+	
+	private ISelection tab = ISelection.selection;
+	
+	private Composite composite;
+	private Function<Composite, T> iSelectionFunction;
+	
+	private Prop<R> prop = new Prop<>();
+	
+	private Map<R, T> map = new HashMap<>();
+	
+	public RaidoHandler(Composite composite, Function<Composite, T> iSelectionFunction) {
+		this.composite = composite;
+		this.iSelectionFunction = iSelectionFunction;
+	}
+	
+	public RaidoHandler<T, R> start() {
+		CompositeUtils.disposeChildren(composite);
+		return this;
+	}
+	
+	public RaidoHandler<T, R> hand(R r, String text) {
+		return hand(r, t -> t.setText(text));
+	}
+	
+	public RaidoHandler<T, R> hand(R r, Consumer<T> setConsumer) {
+		T t = iSelectionFunction.apply(composite);
+		setConsumer.accept(t);
+		t.addMouseListener(MouseListener.mouseUpAdapter($ -> prop.set(r)));
+		map.put(r, t);
+		return this;
+	}
+	
+	public void end() {
+		prop.bind(r -> {
+			tab.setSelection(false);
+			tab = map.get(r);
+			tab.setSelection(true);
+		});
+		composite.layout();
+		composite.getParent().layout();
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		prop.addChangeListener(changeListener);
+	}
+	
+	@Override
+	public R get() {
+		return prop.get();
+	}
+	
+	@Override
+	public void set(R r) {
+		prop.set(r);
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/handler/TabHandler.java b/com.gx.obe.component/src/com/gx/obe/component/handler/TabHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..897e2bc89a8c77dc8a1f12bc4a6ca338a6d02c49
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/handler/TabHandler.java
@@ -0,0 +1,74 @@
+package com.gx.obe.component.handler;
+
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.call.Callback;
+import com.gx.obe.component.utils.CompositeUtils;
+
+public class TabHandler<T extends ISelection> {
+	
+	private ISelection tab;
+	
+	private final Composite composite;
+	private final Function<Composite, T> iTabFunction;
+	
+	private Callback firstCall;
+	
+	public TabHandler(Composite composite, Function<Composite, T> iTabFunction) {
+		this.composite = composite;
+		this.iTabFunction = iTabFunction;
+	}
+	
+	public TabHandler<T> start() {
+		CompositeUtils.disposeChildren(composite);
+		firstCall = null;
+		return this;
+	}
+	
+	public <R> TabHandler<T> hand(String text, Callback callback) {
+		return hand(null, (t, r) -> t.setText(text), r -> callback.call());
+	}
+	
+	public <R> TabHandler<T> hand(Consumer<T> setConsumer, Callback callback) {
+		return hand(null, (t, r) -> setConsumer.accept(t), r -> callback.call());
+	}
+	
+	public <R> TabHandler<T> hand(R r, BiConsumer<T, R> setBiConsumer, Consumer<R> consumer) {
+		T t = iTabFunction.apply(composite);
+		setBiConsumer.accept(t, r);
+		t.addMouseListener(MouseListener.mouseUpAdapter($ -> {
+			tab.setSelection(false);
+			tab = t;
+			tab.setSelection(true);
+			consumer.accept(r);
+		}));
+		if (firstCall == null) firstCall = () -> consumer.accept(r);
+		return this;
+	}
+	
+	public void end() {
+		composite.layout();
+		composite.getParent().layout();
+		CompositeUtils.getFirst(composite).ifPresent(t -> {
+			tab = (ISelection) t;
+			tab.setSelection(true);
+			firstCall.call();
+		});
+	}
+	
+	public <R> TabHandler<T> listHand(List<R> tList, Function<R, String> getTestFunction, Consumer<R> consumer) {
+		return listHand(tList, (t, r) -> t.setText(getTestFunction.apply(r)), consumer);
+	}
+	
+	public <R> TabHandler<T> listHand(List<R> tList, BiConsumer<T, R> setBiConsumer, Consumer<R> consumer) {
+		if (tList != null) tList.forEach(r -> hand(r, setBiConsumer, consumer));
+		return this;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/listener/SelectionListener.java b/com.gx.obe.component/src/com/gx/obe/component/listener/SelectionListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..9b8e1a8b7ca2eb4d3c291df761c48bc80c68a65e
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/listener/SelectionListener.java
@@ -0,0 +1,7 @@
+package com.gx.obe.component.listener;
+
+public interface SelectionListener<T> {
+	
+	void selection(T t);
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/menu/ListMenu.java b/com.gx.obe.component/src/com/gx/obe/component/menu/ListMenu.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd5d14eacef88f68c599f822e34c417f69030941
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/menu/ListMenu.java
@@ -0,0 +1,90 @@
+package com.gx.obe.component.menu;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.eclipse.nebula.widgets.grid.Grid;
+import org.eclipse.nebula.widgets.grid.GridColumn;
+import org.eclipse.nebula.widgets.grid.GridItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Widget;
+
+import com.gx.obe.bind.fun.Fun;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.util.utils.PredicateUtils;
+
+public class ListMenu<T> extends Composite {
+	
+	protected Consumer<T> consumer = t -> {};
+	
+	private Prop<List<T>> tListProp = new Prop<>(new ArrayList<>());
+	private Prop<Integer> menuWidth = new Prop<>(300);
+	
+	/**
+	 * @author chenxw
+	 * @param parent
+	 * @param style
+	 */
+	public ListMenu(Composite parent, Function<T, String> menuNameFun, Function<Composite, Consumer<T>> function) {
+		super(parent, SWT.NONE);
+		setLayout(new GridLayout(2, false));
+		
+		Composite menuComposite = new Composite(this, SWT.NONE);
+		menuComposite.setLayout(new GridLayout(1, false));
+		menuComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 1, 1));
+		
+		Grid grid = new Grid(menuComposite, SWT.V_SCROLL);
+		grid.addSelectionListener(SelectionListener.widgetSelectedAdapter(this::widgetSelected));
+		grid.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		tListProp.bind(l -> {
+			grid.removeAll();
+			l.stream().forEach(t -> {
+				GridItem gridItem = new GridItem(grid, SWT.NONE);
+				gridItem.setText(menuNameFun.apply(t));
+				gridItem.setData(t);
+				gridItem.setHeight(30);
+			});
+			Optional.of(grid).filter(Fun.of(Grid::getItemCount).toTest(PredicateUtils.higher(0))).ifPresent(g -> g.select(0));
+			Optional.of(grid).map(Grid::getSelection).map(Stream::of).flatMap(Stream::findFirst).ifPresent(this::selectItemAction);
+		});
+		
+		GridColumn gridColumn = new GridColumn(grid, SWT.NONE);
+		menuWidth.bind(gridColumn::setWidth);
+		
+		Composite content = new Composite(this, SWT.NONE);
+		content.setLayout(new FillLayout(SWT.HORIZONTAL));
+		content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		consumer = Optional.ofNullable(function).orElseGet(() -> p -> t -> {}).apply(content);
+	}
+	
+	public void refresh(List<T> tList) {
+		tListProp.set(tList);
+	}
+	
+	public void setMenuWidth(int menuWidth) {
+		this.menuWidth.set(menuWidth);
+	}
+	
+	private void widgetSelected(SelectionEvent e) {
+		selectItemAction(e.item);
+	}
+	
+	private void selectItemAction(Widget item) {
+		@SuppressWarnings("unchecked")
+		T t = (T) item.getData();
+		consumer.accept(t);
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/rx/RxSwt.java b/com.gx.obe.component/src/com/gx/obe/component/rx/RxSwt.java
new file mode 100644
index 0000000000000000000000000000000000000000..fef7a3e4032bfa53eae7e2e14c32aab37269c16a
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/rx/RxSwt.java
@@ -0,0 +1,58 @@
+package com.gx.obe.component.rx;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Widget;
+
+import com.gx.obe.bind.promise.Promise;
+import com.gx.obe.bind.rx.RxBind;
+import com.gx.obe.bind.rx.Tangent;
+
+public class RxSwt<T> {
+	
+	private final RxBind<T> rxBind;
+	
+	private Tangent tangent = Tangent.TEMP;
+	private Supplier<Boolean> check = () -> false;
+	private Supplier<T> other = () -> null;
+	
+	public static <T> RxSwt<T> run(Supplier<T> run) {
+		return new RxSwt<T>(run);
+	}
+	
+	public RxSwt<T> setTangent(Tangent tangent) {
+		this.tangent = tangent;
+		return this;
+	}
+	
+	private RxSwt(Supplier<T> run) {
+		rxBind = RxBind.run(run);
+	}
+	
+	public RxSwt<T> checkWidget(Widget widget) {
+		if (widget != null) {
+			this.check = widget::isDisposed;
+		}
+		return this;
+	}
+	
+	public RxSwt<T> other(Supplier<T> other) {
+		this.other = other;
+		return this;
+	}
+	
+	public Promise<T> exe() {
+		return new Promise<>((s, f) -> exe(s));
+	}
+	
+	public void exe(Consumer<T> consumer) {
+		rxBind.supplierSync(this::startThead).consumerSync(Display.getDefault()::asyncExec).tangent(tangent).check(check).other(other).exe(consumer);
+	}
+	
+	private void startThead(Runnable runnable) {
+		new Thread(runnable).start();
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/tabfolder/CTabFolder.java b/com.gx.obe.component/src/com/gx/obe/component/tabfolder/CTabFolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..e71432fbf1245c38ddc2e1885c5b05386832c1d4
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/tabfolder/CTabFolder.java
@@ -0,0 +1,182 @@
+package com.gx.obe.component.tabfolder;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.utils.WidgetUtils;
+import org.eclipse.swt.core.widgets.ESepator;
+import org.eclipse.swt.core.widgets.ImageButton;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.call.Callback;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.component.utils.CompositeUtils;
+import com.swtdesigner.SWTResourceManager;
+
+/**
+ * @Description: 选项卡布局
+ * @author chenxw
+ */
+public abstract class CTabFolder extends Composite {
+	
+	private final StackLayout stackLayout = new StackLayout();
+	
+	private final Composite itemComposite;
+	private final Composite contentComposite;
+	
+	private CTabItem curTabItem;
+	private Composite actionComposite;
+	private int index;
+	
+	/**
+	 * @author chenxw
+	 * @param parent
+	 * @param style
+	 */
+	public CTabFolder(Composite parent, int style) {
+		super(parent, style);
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.verticalSpacing = 0;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		Prop<Boolean> showItemList = new Prop<Boolean>(false);
+		
+		itemComposite = new Composite(this, SWT.NONE);
+		RowLayout rl_composite = new RowLayout(SWT.HORIZONTAL);
+		rl_composite.marginBottom = 0;
+		rl_composite.marginTop = 0;
+		rl_composite.marginRight = 0;
+		rl_composite.marginLeft = 0;
+		itemComposite.setLayout(rl_composite);
+		itemComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		showItemList.bind(t -> WidgetUtils.setControlVisible(itemComposite, t));
+		
+		ESepator timeSep = new ESepator(this, SWT.HORIZONTAL);
+		timeSep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		timeSep.setBackground(ColorConstants.SKIN_BG);
+		timeSep.setLineWidth(3);
+		showItemList.bind(t -> WidgetUtils.setControlVisible(timeSep, t));
+		showItemList.bind(t -> layout());
+		
+		contentComposite = new Composite(this, SWT.NONE);
+		contentComposite.setLayout(stackLayout);
+		contentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		
+		actionComposite = new Composite(contentComposite, SWT.NONE);
+		actionComposite.setLayout(new FillLayout(SWT.HORIZONTAL));
+		
+		init();
+		
+		showItemList.set(itemComposite.getChildren().length > 1);
+	}
+	
+	public void notifyMouseUp() {
+		CompositeUtils.notifyMouseUp(itemComposite);
+	}
+	
+	public void refresh() {
+		if (curTabItem != null) curTabItem.refresh();
+		else CompositeUtils.notifyMouseUp(itemComposite);
+	}
+	
+	/**
+	 * @Description: 初始化
+	 * @author chenxw
+	 */
+	protected abstract void init();
+	
+	/**
+	 * @Description: 选项卡
+	 * @author chenxw
+	 */
+	protected class CTabItem extends ImageButton {
+		
+		private Consumer<Composite> consumer = t -> {};
+		
+		private Callback callback = () -> {};
+		
+		private boolean action;
+		private boolean refresh;
+		
+		private int index = 0;
+		
+		/**
+		 * @author chenxw
+		 * @param text
+		 * @param function
+		 */
+		public CTabItem(String text) {
+			super(itemComposite, SWT.NONE);
+			
+			this.setBorderColor(null);
+			
+			this.setForeground(SWTResourceManager.getColor(127, 127, 127));
+			this.setBackgroundColor(SWTResourceManager.getColor(221, 221, 221));
+			
+			this.setActiveForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+			this.setActiveBgColor(SWTResourceManager.getColor(255, 153, 0));
+			
+			this.setSelectionForeground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+			this.setSelectionBgColor(SWTResourceManager.getColor(60, 138, 226));
+			
+			this.setLeftMargin(15);
+			this.setRightMargin(15);
+			this.setTopMargin(6);
+			this.setBottomMargin(6);
+			
+			setText(text);
+			setFont(SWTResourceManager.getFont("微软雅黑", 9, SWT.BOLD));
+			addMouseListener(MouseListener.mouseUpAdapter(this::mouseUpAction));
+		}
+		
+		public void action(Consumer<Composite> consumer) {
+			this.consumer = Objects.requireNonNull(consumer);
+			this.action = true;
+		}
+		
+		public void refresh(Function<Composite, Callback> function) {
+			this.callback = Objects.requireNonNull(function).apply(contentComposite);
+			this.refresh = true;
+			this.index = ++CTabFolder.this.index;
+		}
+		
+		/**
+		 * @Description: 鼠标点击事件
+		 * @author chenxw
+		 * @param e
+		 */
+		private void mouseUpAction(MouseEvent e) {
+			Optional.ofNullable(curTabItem).ifPresent(t -> t.setSelection(false));
+			this.setSelection(true);
+			curTabItem = this;
+			if (action) stackLayout.topControl = actionComposite;
+			if (refresh) stackLayout.topControl = contentComposite.getChildren()[index];
+			contentComposite.layout();
+			refresh();
+		}
+		
+		private void refresh() {
+			if (action) {
+				CompositeUtils.disposeChildren(actionComposite);
+				consumer.accept(actionComposite);
+				actionComposite.layout();
+			}
+			if (refresh) callback.call();
+		}
+		
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/tabfolder/FTabFolder.java b/com.gx.obe.component/src/com/gx/obe/component/tabfolder/FTabFolder.java
new file mode 100644
index 0000000000000000000000000000000000000000..b5f7bccb84a89526bb7ec27f919f66eeb6d51ac3
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/tabfolder/FTabFolder.java
@@ -0,0 +1,73 @@
+package com.gx.obe.component.tabfolder;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.RView;
+
+/**
+ * @Description: 选项卡布局
+ * @author chenxw
+ * @param <T>
+ */
+public abstract class FTabFolder<T> extends CTabFolder implements RView<T> {
+	
+	private ChangeListener changeListener;
+	
+	private RView<T> rView;
+	
+	/**
+	 * @author chenxw
+	 * @param parent
+	 * @param style
+	 */
+	public FTabFolder(Composite parent, int style) {
+		super(parent, style);
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		this.changeListener = Objects.requireNonNull(changeListener);
+		notifyMouseUp();
+	}
+	
+	@Override
+	public T get() {
+		return Optional.ofNullable(rView).map(RView::get).orElse(null);
+	}
+	
+	/**
+	 * @Description: 选项卡
+	 * @author chenxw
+	 */
+	protected class FTabItem extends CTabFolder.CTabItem {
+		
+		/**
+		 * @author chenxw
+		 * @param text
+		 * @param function
+		 */
+		public FTabItem(String text) {
+			super(text);
+		}
+		
+		/**
+		 * @Description:
+		 * @author chenxw
+		 * @param function
+		 */
+		public void action(Function<Composite, RView<T>> function) {
+			super.action(t -> {
+				rView = function.apply(t);
+				rView.addChangeListener(changeListener);
+				changeListener.change();
+			});
+		}
+		
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/table/CTable.java b/com.gx.obe.component/src/com/gx/obe/component/table/CTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..15d8b1da80c97f271b97ab9d0e7bc8c020c2080c
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/table/CTable.java
@@ -0,0 +1,299 @@
+package com.gx.obe.component.table;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+
+import com.swtdesigner.SWTResourceManager;
+
+import de.kupzog.ktable.KTable;
+import de.kupzog.ktable.KTableCellRenderer;
+import de.kupzog.ktable.SWTX;
+import de.kupzog.ktable.editors.KTableCellEditorLink;
+import de.kupzog.ktable.editors.KTableCellEditorText;
+import de.kupzog.ktable.model.CommonKtableCModel;
+import de.kupzog.ktable.renderers.FixedWrapCellRenderer;
+import de.kupzog.ktable.renderers.LinkCellRenderer;
+import de.kupzog.ktable.renderers.TextWrapCellRenderer;
+
+public class CTable<T> extends KTable {
+	
+	/**
+	 * @Description: 换行文本渲染
+	 */
+	private static final FixedWrapCellRenderer FIXED_RENDERER = new FixedWrapCellRenderer();
+	/**
+	 * @Description: 换行文本渲染
+	 */
+	private static final TextWrapCellRenderer TEXT_RENDERER = new TextWrapCellRenderer();
+	
+	/**
+	 * @Description: 固定行数
+	 */
+	private static final int HEAD_ROW = 1;
+	
+	/**
+	 * @Description: 默认最小列宽
+	 */
+	private static int COLUMN_MIN_WIDTH = -1;
+	/**
+	 * @Description: 默认最小列宽
+	 */
+	private static int COLUMN_WIDTH = -1;
+	/**
+	 * @Description: 默认最大列宽
+	 */
+	private static int COLUMN_MAX_WIDTH = -1;
+	
+	/**
+	 * @Description: 默认列对齐方式
+	 */
+	private static int ALIGN_HORIZONTAL = SWTX.ALIGN_HORIZONTAL_CENTER;
+	
+	/**
+	 * @Description: 固定列
+	 */
+	private final List<Column> headColumnList;
+	/**
+	 * @Description: 内容列
+	 */
+	private final List<Column> contentColumnList;
+	
+	/**
+	 * @Description: 显示数据
+	 */
+	private final List<T> tList;
+	
+	/**
+	 * @Description: 表格模型
+	 */
+	private final CommonKtableCModel commonKtableCModel;
+	
+	public CTable(Composite parent, List<Column> headColumnList, List<Column> contentColumnList, List<T> tList) {
+		super(parent, SWTX.AUTO_SCROLL | SWT.FULL_SELECTION | SWTX.EDIT_ON_KEY | SWTX.FILL_WITH_LASTCOL);
+		this.headColumnList = headColumnList;
+		this.contentColumnList = contentColumnList;
+		this.tList = Optional.ofNullable(tList).orElseGet(ArrayList::new);
+		this.commonKtableCModel = new CommonKtableCModel(this, HEAD_ROW, headColumnList.size(), this.tList.size(), contentColumnList.size());
+		show();
+	}
+	
+	/**
+	 * @Description: 显示
+	 * @author chenxw
+	 */
+	private void show() {
+		for (int col = 0; col < commonKtableCModel.getColCount(); col++) {
+			int minWidth;
+			int width;
+			int maxWidth;
+			if (col < headColumnList.size()) {
+				minWidth = getHeadColumn(col).getMinWidth();
+				width = getHeadColumn(col).getWidth();
+				maxWidth = getHeadColumn(col).getMaxWidth();
+			} else {
+				minWidth = Optional.of(getContentColumn(col)).map(Column::getMinWidth).orElse(COLUMN_MIN_WIDTH);
+				width = Optional.of(getContentColumn(col)).map(Column::getWidth).orElse(COLUMN_WIDTH);
+				maxWidth = Optional.of(getContentColumn(col)).map(Column::getMaxWidth).orElse(COLUMN_MAX_WIDTH);
+			}
+			commonKtableCModel.setColumnMinWidth(col, minWidth);
+			commonKtableCModel.setColumnWidth(col, width);
+			commonKtableCModel.setColumnMaxWidth(col, maxWidth);
+		}
+		
+		commonKtableCModel.setRowHeightRender(row -> 30);
+		commonKtableCModel.setCellBackgroundRender((a, b) -> SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		
+		commonKtableCModel.setCellContentRender(this::receiveContent);
+		commonKtableCModel.setCellRender(this::receiveCellRender);
+		commonKtableCModel.setCellEditorRender(this::receiveCellEditor);
+		commonKtableCModel.setCellImageRender(this::receiveCellImage);
+		commonKtableCModel.setCellAlignmentRender(this::receiveCellAlignment);
+		commonKtableCModel.setCellEditContentRender(this::receiveContent);
+		
+		this.setModel(commonKtableCModel);
+	}
+	
+	/**
+	 * @Description: 加载内容
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private String receiveContent(int row, int col) {
+		if (row < HEAD_ROW) {
+			if (col < headColumnList.size()) {
+				return getHeadColumn(col).getName();
+			}
+			return getContentColumn(col).getName();
+		}
+		if (col < headColumnList.size()) {
+			return getHeadColumn(col).getFunction().apply(row);
+		}
+		return Optional.ofNullable(getContentColumn(col).getFunction().apply(row)).orElse("");
+	}
+	
+	/**
+	 * @Description: 编辑单元格内容
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @param content
+	 * @return 
+	 */
+	private void receiveContent(int row, int col, Object content) {
+		if (commonKtableCModel.isFixedCell(col, row)) {
+			return;
+		}
+		Column contentColumn = getContentColumn(col);
+		if (!(contentColumn instanceof Text)) {
+			return;
+		}
+		@SuppressWarnings("unchecked")
+		Text<T> textContentColumn = (Text<T>) contentColumn;
+		textContentColumn.action(getT(row), content);
+		redraw();
+	}
+	
+	/**
+	 * @Description: 加载渲染器
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private KTableCellRenderer receiveCellRender(int row, int col) {
+		if (commonKtableCModel.isFixedCell(col, row)) {
+			return FIXED_RENDERER;
+		}
+		Column contentColumn = getContentColumn(col);
+		if (!(contentColumn instanceof Link)) {
+			return TEXT_RENDERER;
+		}
+		@SuppressWarnings("unchecked")
+		Link<T> linkContentColumn = (Link<T>) contentColumn;
+		LinkCellRenderer linkCellRenderer = new LinkCellRenderer();
+		linkCellRenderer.setEnable(linkContentColumn.enable(getT(row)));
+		return linkCellRenderer;
+	}
+	
+	/**
+	 * @Description: 加载编辑器
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private Object receiveCellEditor(int row, int col) {
+		if (commonKtableCModel.isFixedCell(col, row)) {
+			return null;
+		}
+		Column contentColumn = getContentColumn(col);
+		if (contentColumn instanceof Link) {
+			return new KTableCellEditorLink(this, this::receiveAction);
+		} else if (contentColumn instanceof Text) {
+			@SuppressWarnings("unchecked")
+			Text<T> textContentColumn = (Text<T>) contentColumn;
+			KTableCellEditorText cellEditorText = new KTableCellEditorText();
+			cellEditorText.setTextLimit(textContentColumn.getTextLimit());
+			return cellEditorText;
+		}
+		return null;
+	}
+	
+	/**
+	 * @Description: 按钮点击事件
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 */
+	private void receiveAction(int row, int col) {
+		if (commonKtableCModel.isFixedCell(col, row)) {
+			return;
+		}
+		Column contentColumn = getContentColumn(col);
+		if (!(contentColumn instanceof Link)) {
+			return;
+		}
+		@SuppressWarnings("unchecked")
+		Link<T> linkContentColumn = (Link<T>) contentColumn;
+		linkContentColumn.action(getT(row));
+	}
+	
+	/**
+	 * @Description: 加载图片
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private Image receiveCellImage(int row, int col) {
+		if (row < HEAD_ROW) {
+			return null;
+		}
+		if (col < headColumnList.size()) {
+			return getHeadColumn(col).getImage();
+		}
+		return getContentColumn(col).getImage();
+	}
+	
+	/**
+	 * @Description: 加载单元格对齐方式
+	 * @author chenxw
+	 * @param row
+	 * @param col
+	 * @return
+	 */
+	private int receiveCellAlignment(int row, int col) {
+		if (row < HEAD_ROW) {
+			return SWTX.ALIGN_VERTICAL_CENTER | SWTX.ALIGN_HORIZONTAL_CENTER;
+		}
+		int align;
+		if (col < headColumnList.size()) {
+			align = Optional.of(getHeadColumn(col)).map(Column::getAlign).orElse(ALIGN_HORIZONTAL);
+		} else {
+			align = Optional.of(getContentColumn(col)).map(Column::getAlign).orElse(ALIGN_HORIZONTAL);
+		}
+		return SWTX.ALIGN_VERTICAL_CENTER | align;
+	}
+	
+	/**
+	 * @Description: 获取固定列
+	 * @author chenxw
+	 * @param col
+	 * @return
+	 */
+	private Column getHeadColumn(int col) {
+		return headColumnList.get(col);
+	}
+	
+	/**
+	 * @Description: 获取内容列
+	 * @author chenxw
+	 * @param col
+	 * @return
+	 */
+	private Column getContentColumn(int col) {
+		return contentColumnList.get(col - headColumnList.size());
+	}
+	
+	/**
+	 * @Description: 获取T
+	 * @author chenxw
+	 * @param row
+	 * @return
+	 */
+	public T getT(int row) {
+		row -= HEAD_ROW;
+		if (tList.size() > row) {
+			return tList.get(row);
+		}
+		return null;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/table/Column.java b/com.gx.obe.component/src/com/gx/obe/component/table/Column.java
new file mode 100644
index 0000000000000000000000000000000000000000..924916aa6b4bdc04bc0148c2b7523d8b36afa14d
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/table/Column.java
@@ -0,0 +1,111 @@
+package com.gx.obe.component.table;
+
+import java.util.function.Function;
+
+import org.eclipse.swt.graphics.Image;
+
+import de.kupzog.ktable.SWTX;
+
+/**
+ * @Description: 列
+ * @author chenxw
+ */
+public class Column {
+	
+	public static final int ALIGN_LEFT = SWTX.ALIGN_HORIZONTAL_LEFT;
+	public static final int ALIGN_CENTER = SWTX.ALIGN_HORIZONTAL_CENTER;
+	public static final int ALIGN_RIGHT = SWTX.ALIGN_HORIZONTAL_RIGHT;
+	
+	/**
+	 * @Description: 名称
+	 */
+	private String name;
+	/**
+	 * @Description: 根据序号获取展示内容
+	 */
+	private Function<Integer, String> function;
+	/**
+	 * @Description: 图片
+	 */
+	private Image image;
+	/**
+	 * @Description: 对齐方式
+	 */
+	private Integer align;
+	/**
+	 * @Description: 最小列宽
+	 */
+	private Integer minWidth;
+	/**
+	 * @Description: 列宽
+	 */
+	private Integer width;
+	/**
+	 * @Description: 最大列宽
+	 */
+	private Integer maxWidth;
+	
+	/**
+	 * @author chenxw
+	 * @param name
+	 * @param function
+	 */
+	public Column(String name, Function<Integer, String> function) {
+		this.name = name;
+		this.function = function;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public Function<Integer, String> getFunction() {
+		return function;
+	}
+	
+	public Column image(Image image) {
+		this.image = image;
+		return this;
+	}
+	
+	public Image getImage() {
+		return image;
+	}
+	
+	public Column align(int align) {
+		this.align = align;
+		return this;
+	}
+	
+	public Integer getAlign() {
+		return align;
+	}
+	
+	public Column minWidth(int minWidth) {
+		this.minWidth = minWidth;
+		return this;
+	}
+	
+	public Integer getMinWidth() {
+		return minWidth;
+	}
+	
+	public Column width(int width) {
+		this.width = width;
+		return this;
+	}
+	
+	public Integer getWidth() {
+		return width;
+	}
+	
+	public Column maxWidth(int maxWidth) {
+		this.maxWidth = maxWidth;
+		return this;
+	}
+	
+	public Integer getMaxWidth() {
+		return maxWidth;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.component/src/com/gx/obe/component/table/FTable.java b/com.gx.obe.component/src/com/gx/obe/component/table/FTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..7abef9983ef7a4072401fe8b104c00182c0a421e
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/table/FTable.java
@@ -0,0 +1,203 @@
+package com.gx.obe.component.table;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.component.listener.SelectionListener;
+import com.gx.obe.component.utils.CompositeUtils;
+
+import de.kupzog.ktable.KTableCellSelectionAdapter;
+
+/**
+ * @Description: 函数式表格
+ * @author chenxw
+ * @param <T>
+ */
+public abstract class FTable<T> extends Composite {
+	
+	/**
+	 * @Description:
+	 */
+	private CTable<T> cTable;
+	
+	/**
+	 * @Description: 获取t函数
+	 */
+	private final Function<Integer, T> tFun = this::getT;
+	
+	/**
+	 * @Description: 固定列
+	 */
+	private final List<Column> headColumnList = new ArrayList<>();
+	/**
+	 * @Description: 内容列
+	 */
+	private final List<Column> contentColumnList = new ArrayList<>();
+	
+	private List<SelectionListener<T>> selectionListenerList = new ArrayList<>();
+	
+	/**
+	 * @author chenxw
+	 * @param parent
+	 * @param tList
+	 */
+	public FTable(Composite parent, int style) {
+		super(parent, style);
+		setLayout(new FillLayout(SWT.HORIZONTAL));
+		init();
+	}
+	
+	/**
+	 * @Description: 初始化
+	 * @author chenxw
+	 */
+	protected abstract void init();
+	
+	/**
+	 * @Description: 刷新
+	 * @author chenxw
+	 * @param tList
+	 */
+	public void refresh(List<T> tList) {
+		CompositeUtils.disposeChildren(this);
+		this.cTable = new CTable<>(this, headColumnList, contentColumnList, tList);
+		cTable.addCellSelectionListener(new KTableCellSelectionAdapter() {
+			public void cellSelected(int col, int row, int statemask) {
+				selection(row);
+			}
+		});
+		this.layout();
+		this.getParent().layout();
+		selection(1);
+	}
+	
+	private void selection(int row) {
+		T t = getT(row);
+		if (t != null) selectionListenerList.forEach(l -> l.selection(t));
+	}
+	
+	public void addSelectionListener(SelectionListener<T> selectionListener) {
+		this.selectionListenerList.add(selectionListener);
+	}
+	
+	/**
+	 * @Description: 获取T
+	 * @author chenxw
+	 * @param row
+	 * @return
+	 */
+	private T getT(int row) {
+		return this.cTable.getT(row);
+	}
+	
+	/**
+	 * @Description: 索引列
+	 * @author chenxw
+	 */
+	protected class IndexColumn extends Column {
+		public IndexColumn(String name) {
+			this(name, 50, String::valueOf);
+		}
+		
+		public IndexColumn(String name, int width, Function<Integer, String> function) {
+			super(name, function);
+			headColumnList.add(this);
+			width(width).minWidth(width).maxWidth(width);
+		}
+	}
+	
+	/**
+	 * @Description: 固定列
+	 * @author chenxw
+	 */
+	protected class HeadColumn extends Column {
+		public HeadColumn(String name, int width, Function<T, String> function) {
+			super(name, tFun.andThen(function));
+			headColumnList.add(this);
+			width(width).minWidth(width).maxWidth(width);
+		}
+	}
+	
+	/**
+	 * @Description: 内容列
+	 * @author chenxw
+	 */
+	protected class ContentColumn extends Column {
+		public ContentColumn(String name, Function<T, String> function) {
+			super(name, tFun.andThen(function));
+			contentColumnList.add(this);
+		}
+	}
+	
+	/**
+	 * @Description: 链接内容列
+	 * @author chenxw
+	 */
+	protected class LinkContentColumn extends ContentColumn implements Link<T> {
+		private Consumer<T> consumer;
+		private Predicate<T> predicate = t -> true;
+		
+		public LinkContentColumn(String name, String content, Image image, Consumer<T> consumer) {
+			super(name, t -> content);
+			image(image);
+			this.consumer = consumer;
+		}
+		
+		public void enable(Predicate<T> predicate) {
+			this.predicate = Objects.requireNonNull(predicate);
+		}
+		
+		@Override
+		public boolean enable(T t) {
+			return predicate.test(t);
+		}
+		
+		@Override
+		public void action(T t) {
+			consumer.accept(t);
+		}
+	}
+	
+	/**
+	 * @Description: 文本编辑内容列
+	 * @author chenxw
+	 */
+	protected class TextContentColumn<R> extends ContentColumn implements Text<T> {
+		
+		private Function<Object, R> format;
+		private BiConsumer<T, R> biConsumer;
+		private int textLimit = 1000;
+		
+		public TextContentColumn(String name, Function<T, String> function, Function<Object, R> format, BiConsumer<T, R> biConsumer) {
+			super(name, function);
+			this.format = format;
+			this.biConsumer = biConsumer;
+		}
+		
+		public void limit(int textLimit) {
+			this.textLimit = textLimit;
+		}
+		
+		@Override
+		public void action(T t, Object content) {
+			biConsumer.accept(t, format.apply(content));
+		}
+		
+		@Override
+		public int getTextLimit() {
+			return textLimit;
+		}
+		
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/table/Link.java b/com.gx.obe.component/src/com/gx/obe/component/table/Link.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b41ca8acbb93046c106acd2b74697163f3859c0
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/table/Link.java
@@ -0,0 +1,14 @@
+package com.gx.obe.component.table;
+
+/**
+ * @Description: 链接
+ * @author chenxw
+ * @param <T>
+ */
+interface Link<T> {
+	
+	boolean enable(T t);
+	
+	void action(T t);
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.component/src/com/gx/obe/component/table/Text.java b/com.gx.obe.component/src/com/gx/obe/component/table/Text.java
new file mode 100644
index 0000000000000000000000000000000000000000..1fc0cbf6606e106d367477865fbed8edd809b333
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/table/Text.java
@@ -0,0 +1,9 @@
+package com.gx.obe.component.table;
+
+public interface Text<T> {
+
+	void action(T t, Object content);
+
+	int getTextLimit();
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/text/CapitalMoneyText.java b/com.gx.obe.component/src/com/gx/obe/component/text/CapitalMoneyText.java
new file mode 100644
index 0000000000000000000000000000000000000000..dac9f2679778b18eaa9c5be5666d8bee9f1e62f3
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/text/CapitalMoneyText.java
@@ -0,0 +1,146 @@
+package com.gx.obe.component.text;
+
+import java.math.BigDecimal;
+import java.util.Objects;
+import java.util.Optional;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import com.gx.obe.bind.fun.Fun;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.MView;
+import com.gx.obe.components.core.util.MoneyUtils;
+import com.swtdesigner.SWTResourceManager;
+
+/**
+ * @Description: 大写金额文本框
+ * @author chenxw
+ */
+public class CapitalMoneyText extends Composite implements MView<BigDecimal> {
+	
+	private final Prop<BigDecimal> moneyProp = new Prop<>(BigDecimal.ZERO);
+	
+	private final Prop<Color> moneyColorProp = new Prop<>(SWTResourceManager.getColor(90, 147, 52));
+	
+	private final Prop<Boolean> editableProp = new Prop<>(true);
+	
+	public CapitalMoneyText(Composite parent, String unit) {
+		super(parent, SWT.NONE);
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		
+		Objects.requireNonNull(unit);
+		
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.verticalSpacing = 0;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		Composite composite = new Composite(this, SWT.NONE);
+		composite.setBackground(SWTResourceManager.getColor(238, 238, 238));
+		GridLayout gl_composite = new GridLayout(3, false);
+		gl_composite.marginHeight = 6;
+		gl_composite.marginWidth = 20;
+		gl_composite.horizontalSpacing = 20;
+		composite.setLayout(gl_composite);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		Label lblNewLabel = new Label(composite, SWT.NONE);
+		lblNewLabel.setForeground(SWTResourceManager.getColor(188, 188, 188));
+		lblNewLabel.setFont(SWTResourceManager.getFont("微软雅黑", 11, SWT.NORMAL));
+		lblNewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+		lblNewLabel.setText("小写");
+		
+		MoneyText text = new MoneyText(composite, SWT.RIGHT, unit);
+		text.setFont(SWTResourceManager.getFont("微软雅黑", 18, SWT.NORMAL));
+		text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		moneyProp.bindBidirectional(text);
+		moneyColorProp.bind(text::setForeground);
+		editableProp.bind(text::setEditable);
+		
+		Label lblNewLabel_2 = new Label(composite, SWT.NONE);
+		lblNewLabel_2.setForeground(SWTResourceManager.getColor(160, 160, 160));
+		lblNewLabel_2.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
+		lblNewLabel_2.setText(unit);
+		
+		Composite composite_1 = new Composite(this, SWT.NONE);
+		composite_1.setBackground(SWTResourceManager.getColor(245, 245, 245));
+		GridLayout gl_composite_1 = new GridLayout(2, false);
+		gl_composite_1.marginHeight = 6;
+		gl_composite_1.marginWidth = 20;
+		gl_composite_1.horizontalSpacing = 20;
+		composite_1.setLayout(gl_composite_1);
+		GridData gd_composite_1 = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+		gd_composite_1.heightHint = 41;
+		composite_1.setLayoutData(gd_composite_1);
+		
+		Label lblNewLabel_1 = new Label(composite_1, SWT.NONE);
+		lblNewLabel_1.setForeground(SWTResourceManager.getColor(188, 188, 188));
+		lblNewLabel_1.setFont(SWTResourceManager.getFont("微软雅黑", 11, SWT.NORMAL));
+		lblNewLabel_1.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, true, 1, 1));
+		lblNewLabel_1.setText("大写");
+		
+		Text text_1 = new Text(composite_1, SWT.RIGHT);
+		text_1.setFont(SWTResourceManager.getFont("微软雅黑", 14, SWT.NORMAL));
+		text_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
+		text_1.setEditable(false);
+		moneyProp.bind(Fun.of(this::moneyToCapital).toWrite(text_1::setText));
+		moneyColorProp.bind(text_1::setForeground);
+		
+	}
+	
+	/**
+	 * @Description: 金额转大写
+	 * @author chenxw
+	 * @param money
+	 * @return
+	 */
+	private String moneyToCapital(BigDecimal money) {
+		return Optional.ofNullable(money).map(BigDecimal::doubleValue).map(MoneyUtils::amountToChinese).orElse("");
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		moneyProp.addChangeListener(changeListener);
+	}
+	
+	@Override
+	public void set(BigDecimal t) {
+		moneyProp.set(t);
+	}
+	
+	/**
+	 * @Description: 设置金额字体颜色
+	 * @author chenxw
+	 * @param moneyColor
+	 */
+	public void setMoneyColor(Color moneyColor) {
+		moneyColorProp.set(moneyColor);
+	}
+	
+	/**
+	 * @Description: 设置是否可编辑
+	 * @author chenxw
+	 * @param editable
+	 */
+	public void setEditable(Boolean editable) {
+		editableProp.set(editable);
+	}
+	
+	@Override
+	public BigDecimal get() {
+		return moneyProp.get();
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.component/src/com/gx/obe/component/text/DocumentText.java b/com.gx.obe.component/src/com/gx/obe/component/text/DocumentText.java
new file mode 100644
index 0000000000000000000000000000000000000000..26bfb7dfc658d709c04fa8144a4e412251b9c49e
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/text/DocumentText.java
@@ -0,0 +1,122 @@
+package com.gx.obe.component.text;
+
+import java.util.function.Supplier;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.MView;
+import com.gx.obe.component.verify.Verify;
+import com.swtdesigner.SWTResourceManager;
+
+/**
+ * @Description:
+ * @author chenxw
+ */
+public class DocumentText extends Composite implements MView<String>, Verify<String> {
+	
+	/**
+	 * @Description: 标题
+	 */
+	private final Prop<String> title = new Prop<>();
+	/**
+	 * @Description: 内容
+	 */
+	private final Prop<String> content = new Prop<>();
+	/**
+	 * @Description: 可编辑
+	 */
+	private final Prop<Boolean> editable = new Prop<>(false);
+	
+	/**
+	 * @Description: 获取内容文本框
+	 */
+	private Supplier<Control> contentTextGet;
+	
+	/**
+	 * @author chenxw
+	 * @param parent
+	 * @param style
+	 */
+	public DocumentText(Composite parent, int style) {
+		super(parent, style);
+		
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		
+		GridLayout gl_composite = new GridLayout(1, false);
+		gl_composite.marginHeight = 0;
+		gl_composite.marginWidth = 50;
+		setLayout(gl_composite);
+		
+		Label titleLabel = new Label(this, SWT.NONE);
+		titleLabel.setFont(SWTResourceManager.getFont("微软雅黑", 12, SWT.NORMAL));
+		titleLabel.setForeground(ColorConstants.TITLE_FONT_COLOR);
+		titleLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		title.bind(titleLabel::setText);
+		
+		StyledText contentText = new StyledText(this, SWT.WRAP | SWT.MULTI);
+		contentText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		contentText.setLineSpacing(10);
+		contentText.setIndent(30);
+		contentText.setFont(SWTResourceManager.getFont("微软雅黑", 12, SWT.NORMAL));
+		contentText.setForeground(ColorConstants.FONT_BLACK_COLOR);
+		editable.bind(contentText::setEditable);
+		content.bindBidirectional(contentText::setText, contentText::getText, t -> contentText.addModifyListener(e -> t.change()));
+		contentTextGet = () -> contentText;
+		
+		Label memoTips = new Label(this, SWT.RIGHT);
+		memoTips.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		content.bind(t -> memoTips.setText("(" + t.length() + "/ " + "500)"));
+	}
+	
+	/**
+	 * @Description: 设置标题
+	 * @author chenxw
+	 * @param title
+	 */
+	public void setTitle(String title) {
+		this.title.set(title);
+	}
+	
+	/**
+	 * @Description: 设置可编辑状态
+	 * @author chenxw
+	 * @param editable 
+	 */
+	public void setEditable(boolean editable) {
+		this.editable.set(editable);
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		content.addChangeListener(changeListener);
+	}
+	
+	@Override
+	public String get() {
+		return content.get();
+	}
+	
+	@Override
+	public void set(String content) {
+		this.content.set(content);
+	}
+	
+	@Override
+	public Supplier<Control> getVerifyControl() {
+		return contentTextGet;
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/text/FStyledText.java b/com.gx.obe.component/src/com/gx/obe/component/text/FStyledText.java
new file mode 100644
index 0000000000000000000000000000000000000000..122e7094c50c3371c8e8957fa5957761502a2551
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/text/FStyledText.java
@@ -0,0 +1,66 @@
+package com.gx.obe.component.text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyleRange;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Composite;
+
+import com.swtdesigner.SWTResourceManager;
+
+public class FStyledText extends StyledText {
+	
+	private StringBuilder textBuilder = new StringBuilder();
+	
+	private List<StyleRange> styleRangeList = new ArrayList<>();
+	
+	public FStyledText(Composite parent) {
+		super(parent, SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.READ_ONLY);
+		this.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
+	}
+	
+	public void clear() {
+		textBuilder.delete(0, textBuilder.length());
+		styleRangeList.clear();
+	}
+	
+	public void refresh() {
+		setText(textBuilder.toString());
+		styleRangeList.forEach(this::setStyleRange);
+	}
+	
+	public void add(String title, String content, Color contentForeground, int contentFontStyle) {
+		if (textBuilder.length() != 0) textBuilder.append("    ");
+		addItem(title, content, contentForeground, contentFontStyle);
+		textBuilder.append(title).append(content);
+	}
+	
+	public void addWrap(String title, String content, Color contentForeground, int contentFontStyle) {
+		textBuilder.append("\r\n");
+		addItem(title, content, contentForeground, contentFontStyle);
+		textBuilder.append(title).append(content);
+	}
+	
+	private void addItem(String title, String content, Color contentForeground, int contentFontStyle) {
+		StyleRange titleStyleRange = new StyleRange();
+		titleStyleRange.start = textBuilder.length();
+		titleStyleRange.length = title.length();
+		titleStyleRange.foreground = SWTResourceManager.getColor(SWT.COLOR_BLUE);
+		titleStyleRange.fontStyle = SWT.BOLD;
+		styleRangeList.add(titleStyleRange);
+		
+		StyleRange contentStyleRange = new StyleRange();
+		contentStyleRange.start = textBuilder.length() + title.length();
+		contentStyleRange.length = content.length();
+		contentStyleRange.foreground = contentForeground;
+		contentStyleRange.fontStyle = contentFontStyle;
+		styleRangeList.add(contentStyleRange);
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/text/IntegerText.java b/com.gx.obe.component/src/com/gx/obe/component/text/IntegerText.java
new file mode 100644
index 0000000000000000000000000000000000000000..76e3f7754698fabc815904249d3a7ff543923b97
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/text/IntegerText.java
@@ -0,0 +1,32 @@
+package com.gx.obe.component.text;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.RView;
+import com.gx.obe.component.verify.IntegerVerifyListener;
+
+public class IntegerText extends Text implements RView<Integer> {
+	
+	public IntegerText(Composite parent, int style) {
+		super(parent, style);
+		addVerifyListener(new IntegerVerifyListener(false));
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		addModifyListener(e -> changeListener.change());
+	}
+	
+	@Override
+	public Integer get() {
+		String text = getText();
+		if (text.isEmpty()) return null;
+		return Integer.valueOf(text);
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/text/MoneyText.java b/com.gx.obe.component/src/com/gx/obe/component/text/MoneyText.java
new file mode 100644
index 0000000000000000000000000000000000000000..f02efe360e37368be308e6d7e2e7aae76daa7254
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/text/MoneyText.java
@@ -0,0 +1,52 @@
+package com.gx.obe.component.text;
+
+import java.math.BigDecimal;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Text;
+
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.MView;
+import com.gx.obe.component.verify.MoneyVerifyListener;
+import com.gx.obe.components.core.enumeration.CommonEnum;
+import com.gx.obe.components.core.util.MoneyUtils;
+
+/**
+ * @Description: 金额输入框
+ * @author chenxw
+ */
+public class MoneyText extends Text implements MView<BigDecimal> {
+	
+	private final String unit;
+	
+	/**
+	 * @author chenxw
+	 * @param parent
+	 * @param style
+	 * @param unit
+	 */
+	public MoneyText(Composite parent, int style, String unit) {
+		super(parent, style);
+		this.unit = unit;
+		addVerifyListener(new MoneyVerifyListener(false, CommonEnum.WAN_YUAN.equals(CommonEnum.getPriceUnitType(unit))));
+	}
+	
+	@Override
+	public void set(BigDecimal t) {
+		setText(MoneyUtils.getMoneyFormatByUnit(t, unit));
+	}
+	
+	@Override
+	public BigDecimal get() {
+		return MoneyUtils.getMoneyFromText(getText(), unit);
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		addModifyListener(e -> changeListener.change());
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.component/src/com/gx/obe/component/text/OrdinaryMoneyText.java b/com.gx.obe.component/src/com/gx/obe/component/text/OrdinaryMoneyText.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8e6d24171efd8eec114ab0270041cf04c25aa60
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/text/OrdinaryMoneyText.java
@@ -0,0 +1,84 @@
+package com.gx.obe.component.text;
+
+import java.math.BigDecimal;
+import java.util.Optional;
+import java.util.function.UnaryOperator;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.widgets.ESepator;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.bind.prop.RProp;
+import com.gx.obe.bind.view.ChangeListener;
+import com.gx.obe.bind.view.RView;
+import com.swtdesigner.SWTResourceManager;
+
+/**
+ * @Description: 小写金额文本框
+ * @author chenxw
+ */
+public class OrdinaryMoneyText extends Composite implements RView<UnaryOperator<BigDecimal>> {
+	
+	/**
+	 * @Description: 金额
+	 */
+	private RProp<BigDecimal> moneyProp = new RProp<BigDecimal>();
+	
+	/**
+	 * @author chenxw
+	 * @param parent
+	 * @param unit
+	 */
+	public OrdinaryMoneyText(Composite parent, String unit) {
+		super(parent, SWT.NONE);
+		setBackground(SWTResourceManager.getColor(239, 243, 248));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.marginWidth = 35;
+		setLayout(gridLayout);
+		
+		Composite composite = new Composite(this, SWT.NONE);
+		GridLayout gl_composite = new GridLayout(3, false);
+		gl_composite.verticalSpacing = 10;
+		gl_composite.horizontalSpacing = 25;
+		composite.setLayout(gl_composite);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
+		
+		Label lblNewLabel = new Label(composite, SWT.NONE);
+		lblNewLabel.setFont(SWTResourceManager.getFont("微软雅黑", 20, SWT.NORMAL));
+		lblNewLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+		lblNewLabel.setText("Â¥");
+		
+		MoneyText text = new MoneyText(composite, SWT.RIGHT, unit);
+		text.setForeground(SWTResourceManager.getColor(204, 204, 204));
+		text.setFont(SWTResourceManager.getFont("微软雅黑", 20, SWT.NORMAL));
+		text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		moneyProp.reader(text);
+		
+		Label lblNewLabel_1 = new Label(composite, SWT.NONE);
+		lblNewLabel_1.setForeground(SWTResourceManager.getColor(157, 157, 157));
+		lblNewLabel_1.setText("万元");
+		
+		ESepator timeSep = new ESepator(composite, SWT.HORIZONTAL);
+		timeSep.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 3, 1));
+		timeSep.setBackground(SWTResourceManager.getColor(153, 153, 153));
+		timeSep.setLineWidth(3);
+	}
+	
+	@Override
+	public UnaryOperator<BigDecimal> get() {
+		return t -> Optional.ofNullable(moneyProp.get()).orElse(t);
+	}
+	
+	@Override
+	public void addChangeListener(ChangeListener changeListener) {
+		moneyProp.addChangeListener(changeListener);
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/tree/ITree.java b/com.gx.obe.component/src/com/gx/obe/component/tree/ITree.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9b9175b038fe11cfaedb05f2d49d51023a81601
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/tree/ITree.java
@@ -0,0 +1,47 @@
+package com.gx.obe.component.tree;
+
+import java.util.List;
+
+/**
+ * @Description: æ ‘
+ * @author chenxw
+ */
+public interface ITree<T extends ITree<T>> {
+	
+	/**
+	 * @Description: 获取树根节点
+	 * @author chenxw
+	 * @return
+	 */
+	ITree<T> getRoot();
+	
+	/**
+	 * @Description: 子树列表
+	 * @author chenxw
+	 * @return
+	 */
+	List<? extends T> getITrees();
+	
+	/**
+	 * @Description: 名称
+	 * @author chenxw
+	 * @return
+	 */
+	String getName();
+	
+	/**
+	 * @Description: é”®
+	 * @author chenxw
+	 * @return
+	 */
+	String getKey();
+	
+	/**
+	 * @Description: 值
+	 * @author chenxw
+	 * @param key
+	 * @return
+	 */
+	String getValue(Object key);
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/tree/ParseTrees.java b/com.gx.obe.component/src/com/gx/obe/component/tree/ParseTrees.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba161ef3992d81dd5a3e3d22eed342d802d331bb
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/tree/ParseTrees.java
@@ -0,0 +1,214 @@
+package com.gx.obe.component.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.gx.obe.util.utils.CollectionUtils;
+
+/**
+ * @Description: 解析树
+ * @author chenxw
+ */
+public class ParseTrees<T extends ITree<T>> {
+	
+	/**
+	 * @Description: 叶子节点列表
+	 */
+	private List<Tree<T>> leafList = new ArrayList<>();
+	
+	/**
+	 * @Description: 树横向合并列表
+	 */
+	private List<TreeSpan> wideSpanList = new ArrayList<>();
+	/**
+	 * @Description: 树竖向合并列表
+	 */
+	private List<TreeSpan> highSpanList = new ArrayList<>();
+	
+	/**
+	 * @Description: 高度
+	 */
+	private int height;
+	/**
+	 * @Description: 叶子节点个数
+	 */
+	private int leafCount;
+	
+	/**
+	 * @Description: 空树
+	 */
+	private final Tree<T> NULL_TREE = new Tree<>();
+	
+	/**
+	 * @author chenxw
+	 * @param iTreeList
+	 */
+	public ParseTrees(List<? extends T> iTreeList) {
+		if (CollectionUtils.isNull(iTreeList)) {
+			return;
+		}
+		initLeafList(iTreeList, 0, null);
+		initHeight(iTreeList, 1);
+		
+		initHighSpanList();
+		initWideSpanList(iTreeList, 0, 0);
+		
+		initLeafCount();
+	}
+	
+	/**
+	 * @Description: 初始化叶子节点列表
+	 * @author chenxw
+	 * @param iTreeList
+	 * @param level
+	 * @param parent
+	 */
+	private void initLeafList(List<? extends T> iTreeList, int level, Tree<T> parent) {
+		for (T iTree : iTreeList) {
+			Tree<T> tree = new Tree<>();
+			tree.setLevel(level);
+			tree.setParent(parent);
+			tree.setValue(iTree);
+			List<? extends T> iTrees = iTree.getITrees();
+			if (CollectionUtils.isNull(iTrees)) leafList.add(tree);
+			else initLeafList(iTrees, level + 1, tree);
+		}
+	}
+	
+	/**
+	 * @Description: 初始化树横向合并列表
+	 * @author chenxw
+	 * @param iTreeList
+	 * @param level
+	 * @param leafIndex
+	 */
+	private int initWideSpanList(List<? extends ITree<T>> iTreeList, int level, int leafIndex) {
+		for (ITree<T> iTree : iTreeList) {
+			List<? extends ITree<T>> iTrees = iTree.getITrees();
+			if (CollectionUtils.isNull(iTrees)) leafIndex++;
+			else {
+				TreeSpan span = new TreeSpan();
+				span.setLevel(level);
+				span.setLeafIndex(leafIndex);
+				span.setSpanCount(iTrees.size());
+				wideSpanList.add(span);
+				leafIndex = initWideSpanList(iTree.getITrees(), level + 1, leafIndex);
+			}
+		}
+		return leafIndex;
+	}
+	
+	/**
+	 * @Description: 初始化树竖向合并列表
+	 * @author chenxw
+	 */
+	private void initHighSpanList() {
+		for (int i = 0; i < leafList.size(); i++) {
+			Tree<T> tree = leafList.get(i);
+			if (height > tree.getLevel()) {
+				TreeSpan span = new TreeSpan();
+				span.setLevel(tree.getLevel());
+				span.setLeafIndex(i);
+				span.setSpanCount(height - tree.getLevel());
+				highSpanList.add(span);
+			}
+		}
+	}
+	
+	/**
+	 * @Description: 初始化树的高度
+	 * @author chenxw
+	 * @param iTreeList
+	 * @param level
+	 */
+	private void initHeight(List<? extends ITree<T>> iTreeList, int level) {
+		for (ITree<T> iTree : iTreeList) {
+			List<? extends ITree<T>> iTrees = iTree.getITrees();
+			if (CollectionUtils.isNull(iTrees)) height = Math.max(height, level);
+			else initHeight(iTrees, level + 1);
+		}
+	}
+	
+	/**
+	 * @Description: 初始化叶子节点的数量
+	 * @author chenxw
+	 */
+	private void initLeafCount() {
+		leafCount = leafList.size();
+	}
+	
+	/**
+	 * @Description: 根据叶子节点索引获取叶子节点
+	 * @author chenxw
+	 * @param leafIndex
+	 * @return
+	 */
+	public T get(int leafIndex) {
+		return leafList.get(leafIndex).getValue();
+	}
+	
+	/**
+	 * @Description: 根据层数及叶子节点索引获取对应包含这个叶子节点是节点
+	 * @author chenxw
+	 * @param level
+	 * @param leafIndex
+	 * @return
+	 */
+	public ITree<T> getITree(int level, int leafIndex) {
+		return getTree(level, leafList.get(leafIndex)).getValue();
+	}
+	
+	/**
+	 * @Description: 根据层数递归获取节点
+	 * @author chenxw
+	 * @param level
+	 * @param tree
+	 * @return
+	 */
+	private Tree<T> getTree(int level, Tree<T> tree) {
+		if (level > tree.getLevel() || level < 0) {
+			return NULL_TREE;
+		}
+		if (level == tree.getLevel()) {
+			return tree;
+		}
+		return getTree(level, tree.getParent());
+	}
+	
+	/**
+	 * @Description: 获取树横向合并列表
+	 * @author chenxw
+	 * @return
+	 */
+	public List<TreeSpan> getWideSpanList() {
+		return wideSpanList;
+	}
+	
+	/**
+	 * @Description: 获取树竖向合并列表
+	 * @author chenxw
+	 * @return
+	 */
+	public List<TreeSpan> getHighSpanList() {
+		return highSpanList;
+	}
+	
+	/**
+	 * @Description: 获取数的高度
+	 * @author chenxw
+	 * @return
+	 */
+	public int getHeight() {
+		return height;
+	}
+	
+	/**
+	 * @Description: 获取叶子节点数
+	 * @author chenxw
+	 * @return
+	 */
+	public int getLeafCount() {
+		return leafCount;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/tree/Tree.java b/com.gx.obe.component/src/com/gx/obe/component/tree/Tree.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3357d00795ac1245ef27e82f6e390e17f387156
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/tree/Tree.java
@@ -0,0 +1,46 @@
+package com.gx.obe.component.tree;
+
+/**
+ * @Description: æ ‘
+ * @author chenxw
+ */
+class Tree<T extends ITree<T>> {
+	
+	/**
+	 * @Description: 层数
+	 */
+	private int level;
+	/**
+	 * @Description: 父节点
+	 */
+	private Tree<T> parent;
+	/**
+	 * @Description: 值
+	 */
+	private T value;
+	
+	public int getLevel() {
+		return level;
+	}
+	
+	public void setLevel(int level) {
+		this.level = level;
+	}
+	
+	public Tree<T> getParent() {
+		return parent;
+	}
+	
+	public void setParent(Tree<T> parent) {
+		this.parent = parent;
+	}
+	
+	public T getValue() {
+		return value;
+	}
+	
+	public void setValue(T value) {
+		this.value = value;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.component/src/com/gx/obe/component/tree/TreeSpan.java b/com.gx.obe.component/src/com/gx/obe/component/tree/TreeSpan.java
new file mode 100644
index 0000000000000000000000000000000000000000..b54023411e7113ea45acd011172e481bde720dc8
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/tree/TreeSpan.java
@@ -0,0 +1,35 @@
+package com.gx.obe.component.tree;
+
+public class TreeSpan {
+	
+	private int level;
+	
+	private int leafIndex;
+	
+	private int spanCount;
+	
+	public int getLevel() {
+		return level;
+	}
+	
+	public void setLevel(int level) {
+		this.level = level;
+	}
+	
+	public int getLeafIndex() {
+		return leafIndex;
+	}
+	
+	public void setLeafIndex(int leafIndex) {
+		this.leafIndex = leafIndex;
+	}
+	
+	public int getSpanCount() {
+		return spanCount;
+	}
+	
+	public void setSpanCount(int spanCount) {
+		this.spanCount = spanCount;
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/utils/CompositeUtils.java b/com.gx.obe.component/src/com/gx/obe/component/utils/CompositeUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..b6189c2a37905638be5648c54bd96f4e4d1a470a
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/utils/CompositeUtils.java
@@ -0,0 +1,24 @@
+package com.gx.obe.component.utils;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+public class CompositeUtils {
+	
+	public static void disposeChildren(Composite composite) {
+		Arrays.stream(composite.getChildren()).forEach(Control::dispose);
+	}
+	
+	public static void notifyMouseUp(Composite composite) {
+		CompositeUtils.getFirst(composite).ifPresent(t -> t.notifyListeners(SWT.MouseUp, null));
+	}
+	
+	public static Optional<Control> getFirst(Composite composite) {
+		return Arrays.stream(composite.getChildren()).findFirst();
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/verify/FormVerify.java b/com.gx.obe.component/src/com/gx/obe/component/verify/FormVerify.java
new file mode 100644
index 0000000000000000000000000000000000000000..96ee3e8ef690fc87f2116ba6b0a63c483b9ccb11
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/verify/FormVerify.java
@@ -0,0 +1,57 @@
+package com.gx.obe.component.verify;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.widgets.Control;
+
+import com.gx.obe.bind.fun.Fun;
+
+public class FormVerify {
+	
+	List<Data> datas = new ArrayList<>();
+	
+	public <T> void verify(Verify<T> verify, Function<T, Boolean> discontentCondition, String message) {
+		datas.add(new Data(verify.getVerifyControl(), Fun.of(discontentCondition).toGet(verify::get), message));
+	}
+	
+	public void verify(Control control, Supplier<Boolean> discontentCondition, String message) {
+		datas.add(new Data(() -> control, discontentCondition, message));
+	}
+	
+	public void add(FormVerify formVerify) {
+		datas.addAll(formVerify.getDatas());
+	}
+	
+	public boolean isFail() {
+		for (Data data : datas) {
+			if (data.discontentCondition.get()) {
+				MessageDialog.openWarning(data.controlGet.get().getShell(), data.message);
+				data.controlGet.get().setFocus();
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	private List<Data> getDatas() {
+		return datas;
+	}
+	
+	class Data {
+		Supplier<Control> controlGet;
+		Supplier<Boolean> discontentCondition;
+		String message;
+		
+		public Data(Supplier<Control> controlGet, Supplier<Boolean> discontentCondition, String message) {
+			this.controlGet = controlGet;
+			this.discontentCondition = discontentCondition;
+			this.message = message;
+		}
+		
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/verify/IntegerVerifyListener.java b/com.gx.obe.component/src/com/gx/obe/component/verify/IntegerVerifyListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..bdbf52ec96887eebe54ebb3ea81d1aba25fbb658
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/verify/IntegerVerifyListener.java
@@ -0,0 +1,50 @@
+package com.gx.obe.component.verify;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * @Description: 整数验证监听
+ * @author chenxw
+ */
+public class IntegerVerifyListener implements VerifyListener {
+	
+	private boolean negativeSupport;
+	
+	/**
+	 * @author chenxw
+	 * @param negativeSupport
+	 */
+	public IntegerVerifyListener(boolean negativeSupport) {
+		this.negativeSupport = negativeSupport;
+	}
+	
+	@Override
+	public void verifyText(VerifyEvent event) {
+		if (event.keyCode == SWT.BS || event.keyCode == SWT.DEL) {
+			event.doit = true;
+			return;
+		}
+		event.doit = false;
+		char myChar = event.character;
+		Text text = (Text) event.widget;
+		String textStr = text.getText();
+		if (myChar == '-') {
+			if (negativeSupport) {
+				if (textStr.indexOf("-") == -1) {
+					if (event.start == 0) {
+						event.doit = true;
+					}
+				}
+			}
+		} else {
+			// 其余的只能输入数字
+			if ((myChar >= '0' && myChar <= '9')) {
+				event.doit = true;
+			}
+		}
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/verify/MoneyVerifyListener.java b/com.gx.obe.component/src/com/gx/obe/component/verify/MoneyVerifyListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..0d90939e28240b4f10036fe1f6c38abada9ce5d3
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/verify/MoneyVerifyListener.java
@@ -0,0 +1,89 @@
+package com.gx.obe.component.verify;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.widgets.Text;
+
+/**
+ * @Description: 金额验证接听
+ * @author chenxw
+ */
+public class MoneyVerifyListener implements VerifyListener {
+	
+	private boolean negativeSupport;
+	private boolean tenThousand;
+	
+	/**
+	 * @author chenxw
+	 * @param negativeSupport
+	 * @param tenThousand
+	 */
+	public MoneyVerifyListener(boolean negativeSupport, boolean tenThousand) {
+		this.negativeSupport = negativeSupport;
+		this.tenThousand = tenThousand;
+	}
+	
+	@Override
+	public void verifyText(VerifyEvent event) {
+		if (event.keyCode == SWT.BS || event.keyCode == SWT.DEL) {
+			event.doit = true;
+			return;
+		}
+		event.doit = false;
+		char myChar = event.character;
+		Text text = (Text) event.widget;
+		String textStr = text.getText();
+		
+		// 当通过代码set值时
+		if (myChar == 0) {
+			event.doit = true;
+		}
+		// 当输入负号时
+		else if (myChar == '-') {
+			// 支持负数
+			if (negativeSupport) {
+				// 当前文本中没有负号
+				if (textStr.indexOf("-") == -1) {
+					// 第一次输入
+					if (event.start == 0) {
+						event.doit = true;
+					}
+				}
+			}
+		}
+		// 当输入小数点时
+		else if (myChar == '.') {
+			// 当前文本中没有小数点
+			if (textStr.indexOf(".") == -1) {
+				// 不是第一次输入
+				if (event.start != 0) {
+					event.doit = true;
+				}
+			}
+		}
+		// 当输入数字时
+		else if ((myChar >= '0' && myChar <= '9')) {
+			// 第一次输入
+			if (textStr.isEmpty()) {
+				event.doit = true;
+			} else {
+				String integralPart = textStr;
+				int indexOf = textStr.indexOf('.');
+				// 当前文本中有小数点时截取整数部分
+				if (indexOf != -1) {
+					integralPart = textStr.substring(0, indexOf);
+				}
+				// 当前整数部分是以负号开始时去掉负号
+				if (integralPart.startsWith("-")) {
+					integralPart = integralPart.substring(1);
+				}
+				// 去掉负号后的整数部分长度不能超过金额限定长度
+				if (integralPart.length() < (tenThousand ? 10 : 14)) {
+					event.doit = true;
+				}
+			}
+		}
+	}
+	
+}
diff --git a/com.gx.obe.component/src/com/gx/obe/component/verify/Verify.java b/com.gx.obe.component/src/com/gx/obe/component/verify/Verify.java
new file mode 100644
index 0000000000000000000000000000000000000000..2eaf6acd1b38b6f12bf7e2fb735b2f834533e7f3
--- /dev/null
+++ b/com.gx.obe.component/src/com/gx/obe/component/verify/Verify.java
@@ -0,0 +1,11 @@
+package com.gx.obe.component.verify;
+
+import java.util.function.Supplier;
+
+import org.eclipse.swt.widgets.Control;
+
+import com.gx.obe.bind.view.Read;
+
+public interface Verify<T> extends Read<T> {
+	Supplier<Control> getVerifyControl();
+}
\ No newline at end of file
diff --git a/com.gx.obe.component/src/org/eclipse/wb/swt/SWTResourceManager.java b/com.gx.obe.component/src/org/eclipse/wb/swt/SWTResourceManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..d8a285807adcefed53ca8b9d3af0f7d9881e1a13
--- /dev/null
+++ b/com.gx.obe.component/src/org/eclipse/wb/swt/SWTResourceManager.java
@@ -0,0 +1,447 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Google, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Google, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wb.swt;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Cursor;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+
+/**
+ * Utility class for managing OS resources associated with SWT controls such as colors, fonts, images, etc.
+ * <p>
+ * !!! IMPORTANT !!! Application code must explicitly invoke the <code>dispose()</code> method to release the
+ * operating system resources managed by cached objects when those objects and OS resources are no longer
+ * needed (e.g. on application shutdown)
+ * <p>
+ * This class may be freely distributed as part of any application or plugin.
+ * <p>
+ * @author scheglov_ke
+ * @author Dan Rubel
+ */
+public class SWTResourceManager {
+	////////////////////////////////////////////////////////////////////////////
+	//
+	// Color
+	//
+	////////////////////////////////////////////////////////////////////////////
+	private static Map<RGB, Color> m_colorMap = new HashMap<RGB, Color>();
+	/**
+	 * Returns the system {@link Color} matching the specific ID.
+	 * 
+	 * @param systemColorID
+	 *            the ID value for the color
+	 * @return the system {@link Color} matching the specific ID
+	 */
+	public static Color getColor(int systemColorID) {
+		Display display = Display.getCurrent();
+		return display.getSystemColor(systemColorID);
+	}
+	/**
+	 * Returns a {@link Color} given its red, green and blue component values.
+	 * 
+	 * @param r
+	 *            the red component of the color
+	 * @param g
+	 *            the green component of the color
+	 * @param b
+	 *            the blue component of the color
+	 * @return the {@link Color} matching the given red, green and blue component values
+	 */
+	public static Color getColor(int r, int g, int b) {
+		return getColor(new RGB(r, g, b));
+	}
+	/**
+	 * Returns a {@link Color} given its RGB value.
+	 * 
+	 * @param rgb
+	 *            the {@link RGB} value of the color
+	 * @return the {@link Color} matching the RGB value
+	 */
+	public static Color getColor(RGB rgb) {
+		Color color = m_colorMap.get(rgb);
+		if (color == null) {
+			Display display = Display.getCurrent();
+			color = new Color(display, rgb);
+			m_colorMap.put(rgb, color);
+		}
+		return color;
+	}
+	/**
+	 * Dispose of all the cached {@link Color}'s.
+	 */
+	public static void disposeColors() {
+		for (Color color : m_colorMap.values()) {
+			color.dispose();
+		}
+		m_colorMap.clear();
+	}
+	////////////////////////////////////////////////////////////////////////////
+	//
+	// Image
+	//
+	////////////////////////////////////////////////////////////////////////////
+	/**
+	 * Maps image paths to images.
+	 */
+	private static Map<String, Image> m_imageMap = new HashMap<String, Image>();
+	/**
+	 * Returns an {@link Image} encoded by the specified {@link InputStream}.
+	 * 
+	 * @param stream
+	 *            the {@link InputStream} encoding the image data
+	 * @return the {@link Image} encoded by the specified input stream
+	 */
+	protected static Image getImage(InputStream stream) throws IOException {
+		try {
+			Display display = Display.getCurrent();
+			ImageData data = new ImageData(stream);
+			if (data.transparentPixel > 0) {
+				return new Image(display, data, data.getTransparencyMask());
+			}
+			return new Image(display, data);
+		} finally {
+			stream.close();
+		}
+	}
+	/**
+	 * Returns an {@link Image} stored in the file at the specified path.
+	 * 
+	 * @param path
+	 *            the path to the image file
+	 * @return the {@link Image} stored in the file at the specified path
+	 */
+	public static Image getImage(String path) {
+		Image image = m_imageMap.get(path);
+		if (image == null) {
+			try {
+				image = getImage(new FileInputStream(path));
+				m_imageMap.put(path, image);
+			} catch (Exception e) {
+				image = getMissingImage();
+				m_imageMap.put(path, image);
+			}
+		}
+		return image;
+	}
+	/**
+	 * Returns an {@link Image} stored in the file at the specified path relative to the specified class.
+	 * 
+	 * @param clazz
+	 *            the {@link Class} relative to which to find the image
+	 * @param path
+	 *            the path to the image file, if starts with <code>'/'</code>
+	 * @return the {@link Image} stored in the file at the specified path
+	 */
+	public static Image getImage(Class<?> clazz, String path) {
+		String key = clazz.getName() + '|' + path;
+		Image image = m_imageMap.get(key);
+		if (image == null) {
+			try {
+				image = getImage(clazz.getResourceAsStream(path));
+				m_imageMap.put(key, image);
+			} catch (Exception e) {
+				image = getMissingImage();
+				m_imageMap.put(key, image);
+			}
+		}
+		return image;
+	}
+	private static final int MISSING_IMAGE_SIZE = 10;
+	/**
+	 * @return the small {@link Image} that can be used as placeholder for missing image.
+	 */
+	private static Image getMissingImage() {
+		Image image = new Image(Display.getCurrent(), MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
+		//
+		GC gc = new GC(image);
+		gc.setBackground(getColor(SWT.COLOR_RED));
+		gc.fillRectangle(0, 0, MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
+		gc.dispose();
+		//
+		return image;
+	}
+	/**
+	 * Style constant for placing decorator image in top left corner of base image.
+	 */
+	public static final int TOP_LEFT = 1;
+	/**
+	 * Style constant for placing decorator image in top right corner of base image.
+	 */
+	public static final int TOP_RIGHT = 2;
+	/**
+	 * Style constant for placing decorator image in bottom left corner of base image.
+	 */
+	public static final int BOTTOM_LEFT = 3;
+	/**
+	 * Style constant for placing decorator image in bottom right corner of base image.
+	 */
+	public static final int BOTTOM_RIGHT = 4;
+	/**
+	 * Internal value.
+	 */
+	protected static final int LAST_CORNER_KEY = 5;
+	/**
+	 * Maps images to decorated images.
+	 */
+	@SuppressWarnings("unchecked")
+	private static Map<Image, Map<Image, Image>>[] m_decoratedImageMap = new Map[LAST_CORNER_KEY];
+	/**
+	 * Returns an {@link Image} composed of a base image decorated by another image.
+	 * 
+	 * @param baseImage
+	 *            the base {@link Image} that should be decorated
+	 * @param decorator
+	 *            the {@link Image} to decorate the base image
+	 * @return {@link Image} The resulting decorated image
+	 */
+	public static Image decorateImage(Image baseImage, Image decorator) {
+		return decorateImage(baseImage, decorator, BOTTOM_RIGHT);
+	}
+	/**
+	 * Returns an {@link Image} composed of a base image decorated by another image.
+	 * 
+	 * @param baseImage
+	 *            the base {@link Image} that should be decorated
+	 * @param decorator
+	 *            the {@link Image} to decorate the base image
+	 * @param corner
+	 *            the corner to place decorator image
+	 * @return the resulting decorated {@link Image}
+	 */
+	public static Image decorateImage(final Image baseImage, final Image decorator, final int corner) {
+		if (corner <= 0 || corner >= LAST_CORNER_KEY) {
+			throw new IllegalArgumentException("Wrong decorate corner");
+		}
+		Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[corner];
+		if (cornerDecoratedImageMap == null) {
+			cornerDecoratedImageMap = new HashMap<Image, Map<Image, Image>>();
+			m_decoratedImageMap[corner] = cornerDecoratedImageMap;
+		}
+		Map<Image, Image> decoratedMap = cornerDecoratedImageMap.get(baseImage);
+		if (decoratedMap == null) {
+			decoratedMap = new HashMap<Image, Image>();
+			cornerDecoratedImageMap.put(baseImage, decoratedMap);
+		}
+		//
+		Image result = decoratedMap.get(decorator);
+		if (result == null) {
+			Rectangle bib = baseImage.getBounds();
+			Rectangle dib = decorator.getBounds();
+			//
+			result = new Image(Display.getCurrent(), bib.width, bib.height);
+			//
+			GC gc = new GC(result);
+			gc.drawImage(baseImage, 0, 0);
+			if (corner == TOP_LEFT) {
+				gc.drawImage(decorator, 0, 0);
+			} else if (corner == TOP_RIGHT) {
+				gc.drawImage(decorator, bib.width - dib.width, 0);
+			} else if (corner == BOTTOM_LEFT) {
+				gc.drawImage(decorator, 0, bib.height - dib.height);
+			} else if (corner == BOTTOM_RIGHT) {
+				gc.drawImage(decorator, bib.width - dib.width, bib.height - dib.height);
+			}
+			gc.dispose();
+			//
+			decoratedMap.put(decorator, result);
+		}
+		return result;
+	}
+	/**
+	 * Dispose all of the cached {@link Image}'s.
+	 */
+	public static void disposeImages() {
+		// dispose loaded images
+		{
+			for (Image image : m_imageMap.values()) {
+				image.dispose();
+			}
+			m_imageMap.clear();
+		}
+		// dispose decorated images
+		for (int i = 0; i < m_decoratedImageMap.length; i++) {
+			Map<Image, Map<Image, Image>> cornerDecoratedImageMap = m_decoratedImageMap[i];
+			if (cornerDecoratedImageMap != null) {
+				for (Map<Image, Image> decoratedMap : cornerDecoratedImageMap.values()) {
+					for (Image image : decoratedMap.values()) {
+						image.dispose();
+					}
+					decoratedMap.clear();
+				}
+				cornerDecoratedImageMap.clear();
+			}
+		}
+	}
+	////////////////////////////////////////////////////////////////////////////
+	//
+	// Font
+	//
+	////////////////////////////////////////////////////////////////////////////
+	/**
+	 * Maps font names to fonts.
+	 */
+	private static Map<String, Font> m_fontMap = new HashMap<String, Font>();
+	/**
+	 * Maps fonts to their bold versions.
+	 */
+	private static Map<Font, Font> m_fontToBoldFontMap = new HashMap<Font, Font>();
+	/**
+	 * Returns a {@link Font} based on its name, height and style.
+	 * 
+	 * @param name
+	 *            the name of the font
+	 * @param height
+	 *            the height of the font
+	 * @param style
+	 *            the style of the font
+	 * @return {@link Font} The font matching the name, height and style
+	 */
+	public static Font getFont(String name, int height, int style) {
+		return getFont(name, height, style, false, false);
+	}
+	/**
+	 * Returns a {@link Font} based on its name, height and style. Windows-specific strikeout and underline
+	 * flags are also supported.
+	 * 
+	 * @param name
+	 *            the name of the font
+	 * @param size
+	 *            the size of the font
+	 * @param style
+	 *            the style of the font
+	 * @param strikeout
+	 *            the strikeout flag (warning: Windows only)
+	 * @param underline
+	 *            the underline flag (warning: Windows only)
+	 * @return {@link Font} The font matching the name, height, style, strikeout and underline
+	 */
+	public static Font getFont(String name, int size, int style, boolean strikeout, boolean underline) {
+		String fontName = name + '|' + size + '|' + style + '|' + strikeout + '|' + underline;
+		Font font = m_fontMap.get(fontName);
+		if (font == null) {
+			FontData fontData = new FontData(name, size, style);
+			if (strikeout || underline) {
+				try {
+					Class<?> logFontClass = Class.forName("org.eclipse.swt.internal.win32.LOGFONT"); //$NON-NLS-1$
+					Object logFont = FontData.class.getField("data").get(fontData); //$NON-NLS-1$
+					if (logFont != null && logFontClass != null) {
+						if (strikeout) {
+							logFontClass.getField("lfStrikeOut").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$
+						}
+						if (underline) {
+							logFontClass.getField("lfUnderline").set(logFont, Byte.valueOf((byte) 1)); //$NON-NLS-1$
+						}
+					}
+				} catch (Throwable e) {
+					System.err.println("Unable to set underline or strikeout" + " (probably on a non-Windows platform). " + e); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}
+			font = new Font(Display.getCurrent(), fontData);
+			m_fontMap.put(fontName, font);
+		}
+		return font;
+	}
+	/**
+	 * Returns a bold version of the given {@link Font}.
+	 * 
+	 * @param baseFont
+	 *            the {@link Font} for which a bold version is desired
+	 * @return the bold version of the given {@link Font}
+	 */
+	public static Font getBoldFont(Font baseFont) {
+		Font font = m_fontToBoldFontMap.get(baseFont);
+		if (font == null) {
+			FontData fontDatas[] = baseFont.getFontData();
+			FontData data = fontDatas[0];
+			font = new Font(Display.getCurrent(), data.getName(), data.getHeight(), SWT.BOLD);
+			m_fontToBoldFontMap.put(baseFont, font);
+		}
+		return font;
+	}
+	/**
+	 * Dispose all of the cached {@link Font}'s.
+	 */
+	public static void disposeFonts() {
+		// clear fonts
+		for (Font font : m_fontMap.values()) {
+			font.dispose();
+		}
+		m_fontMap.clear();
+		// clear bold fonts
+		for (Font font : m_fontToBoldFontMap.values()) {
+			font.dispose();
+		}
+		m_fontToBoldFontMap.clear();
+	}
+	////////////////////////////////////////////////////////////////////////////
+	//
+	// Cursor
+	//
+	////////////////////////////////////////////////////////////////////////////
+	/**
+	 * Maps IDs to cursors.
+	 */
+	private static Map<Integer, Cursor> m_idToCursorMap = new HashMap<Integer, Cursor>();
+	/**
+	 * Returns the system cursor matching the specific ID.
+	 * 
+	 * @param id
+	 *            int The ID value for the cursor
+	 * @return Cursor The system cursor matching the specific ID
+	 */
+	public static Cursor getCursor(int id) {
+		Integer key = Integer.valueOf(id);
+		Cursor cursor = m_idToCursorMap.get(key);
+		if (cursor == null) {
+			cursor = new Cursor(Display.getDefault(), id);
+			m_idToCursorMap.put(key, cursor);
+		}
+		return cursor;
+	}
+	/**
+	 * Dispose all of the cached cursors.
+	 */
+	public static void disposeCursors() {
+		for (Cursor cursor : m_idToCursorMap.values()) {
+			cursor.dispose();
+		}
+		m_idToCursorMap.clear();
+	}
+	////////////////////////////////////////////////////////////////////////////
+	//
+	// General
+	//
+	////////////////////////////////////////////////////////////////////////////
+	/**
+	 * Dispose of cached objects and their underlying OS resources. This should only be called when the cached
+	 * objects are no longer needed (e.g. on application shutdown).
+	 */
+	public static void dispose() {
+		disposeColors();
+		disposeImages();
+		disposeFonts();
+		disposeCursors();
+	}
+}
\ No newline at end of file
diff --git a/com.gx.obe.quote/src/com/gx/obe/quote/dialog/AdjustStrategyDialog.java b/com.gx.obe.quote/src/com/gx/obe/quote/dialog/AdjustStrategyDialog.java
index 5a36a81fbebf86a144767820f0252d26de5b7e35..a8fd68fbdd5139ace92eb4394905965c69ea6701 100644
--- a/com.gx.obe.quote/src/com/gx/obe/quote/dialog/AdjustStrategyDialog.java
+++ b/com.gx.obe.quote/src/com/gx/obe/quote/dialog/AdjustStrategyDialog.java
@@ -242,7 +242,7 @@ public class AdjustStrategyDialog extends EDialog {
 		String adjustReason = adjustReason_text.getText().trim();
 		if (VerificationUtils.ver(adjustReason_text, adjustReason::isEmpty, "调整原因不能为空!")) return;
 		
-		if (evaluationStepService.isCompletePriceAndRecommendStep(tenderId)) {
+		if (evaluationStepService.isCompletePriceAndRecommonedStep(tenderId)) {
 			MessageDialog.openWarning(getShell(), "已完成价格评审或推荐中标候选人,无法调整评标价!");
 			return;
 		}
diff --git a/com.gx.obe.quote/src/com/gx/obe/quote/dialog/ModifyBidPriceDialog.java b/com.gx.obe.quote/src/com/gx/obe/quote/dialog/ModifyBidPriceDialog.java
index ef2ee16c0eeaae6c1387f1263646c5763cf2de47..44881ad4ce9d729d0d905d88f04311c0abac9fc0 100644
--- a/com.gx.obe.quote/src/com/gx/obe/quote/dialog/ModifyBidPriceDialog.java
+++ b/com.gx.obe.quote/src/com/gx/obe/quote/dialog/ModifyBidPriceDialog.java
@@ -28,11 +28,12 @@ import com.gx.obe.quote.listener.PatternModifyListener;
 import com.gx.obe.quote.utils.VerificationUtils;
 import com.gx.obe.quote.vo.BidPriceModifyVo;
 import com.gx.obe.quote.vo.QuoteVo;
-import com.gx.obe.util.utils.BigDecimalUtil;
 import com.gx.obe.web.service.BidPriceResultService;
 import com.gx.obe.web.service.evaluation.EvaluationStepService;
 import com.swtdesigner.SWTResourceManager;
 
+import im.util.BigDecimalUtil;
+
 /**
  * @Description: 修正投标报价
  * @author chenxw
@@ -224,7 +225,7 @@ public class ModifyBidPriceDialog extends EDialog {
 		String modifyReason = modifyReason_text.getText();
 		if (VerificationUtils.ver(modifyReason_text, modifyReason::isEmpty, "修正原因不能为空!")) return;
 		
-		if (evaluationStepService.isCompletePriceAndRecommendStep(tenderId)) {
+		if (evaluationStepService.isCompletePriceAndRecommonedStep(tenderId)) {
 			MessageDialog.openWarning(getShell(), "已完成价格评审或推荐中标候选人,无法修正投标价!");
 			return;
 		}
diff --git a/com.gx.obe.quote/src/com/gx/obe/quote/table/AdjustStrategyTable.java b/com.gx.obe.quote/src/com/gx/obe/quote/table/AdjustStrategyTable.java
index 95ee2c81c48cd2ef89b9831c10442dc5c8884d40..91a384c12a119a256e313c9fe95eb11b76a67c2b 100644
--- a/com.gx.obe.quote/src/com/gx/obe/quote/table/AdjustStrategyTable.java
+++ b/com.gx.obe.quote/src/com/gx/obe/quote/table/AdjustStrategyTable.java
@@ -61,7 +61,7 @@ public class AdjustStrategyTable extends DynamicTable {
 	}
 	
 	private void refreshTable() {
-		if (!evaluationStepService.isCompletePriceAndRecommendStep(tenderId)) {
+		if (!evaluationStepService.isCompletePriceAndRecommonedStep(tenderId)) {
 			addOperateCol(new OperateColVo("操作", "调整", editImage, this::editEnablePre, this::editActionRender));
 			addOperateCol(new OperateColVo("操作", "重置", deleteImage, this::deleteEnablePre, this::deleteActionRender));
 		}
diff --git a/com.gx.obe.quote/src/com/gx/obe/quote/table/BidPriceModifyTable.java b/com.gx.obe.quote/src/com/gx/obe/quote/table/BidPriceModifyTable.java
index 70625953e46b282e98474fbd1b426f914661fe11..38443fd6ebdafffc2a4aea575bc71b10fdcf855c 100644
--- a/com.gx.obe.quote/src/com/gx/obe/quote/table/BidPriceModifyTable.java
+++ b/com.gx.obe.quote/src/com/gx/obe/quote/table/BidPriceModifyTable.java
@@ -78,7 +78,7 @@ public class BidPriceModifyTable extends DynamicTable {
 	}
 	
 	private void refreshTable() {
-		if (!evaluationStepService.isCompletePriceAndRecommendStep(tenderId)) {
+		if (!evaluationStepService.isCompletePriceAndRecommonedStep(tenderId)) {
 			addOperateCol(new OperateColVo("操作", "修正", editImage, this::editEnablePre, this::editActionRender));
 			addOperateCol(new OperateColVo("操作", "重置", deleteImage, this::deleteEnablePre, this::deleteActionRender));
 		}
diff --git a/com.gx.obe.step.appraise/src/com/gx/obe/step/appraise/utils/UserUtils.java b/com.gx.obe.step.appraise/src/com/gx/obe/step/appraise/utils/UserUtils.java
index 4a8f894b18020ab0c09e567b2306d6f748a6dee7..1c8fa2211c2613d68dfd72e3ec7849d915f7bfc4 100644
--- a/com.gx.obe.step.appraise/src/com/gx/obe/step/appraise/utils/UserUtils.java
+++ b/com.gx.obe.step.appraise/src/com/gx/obe/step/appraise/utils/UserUtils.java
@@ -32,11 +32,11 @@ public class UserUtils {
 	}
 	
 	public static List<AuthUser> getManagerUserList(String userId) {
-		return Stream.of(userService.getById(userId)).collect(Collectors.toList());
+		return Stream.of(userService.findById(userId)).collect(Collectors.toList());
 	}
 	
 	public static AuthUser getManagerUser(String tenderId) {
-		return userService.getById(tenderProjectService.getById(tenderId).getUserId());
+		return userService.findById(tenderProjectService.getById(tenderId).getUserId());
 	}
 	
 }
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/calculator/SupplierPriceEvalResultCalculator.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/calculator/SupplierPriceEvalResultCalculator.java
index 188a94ec2fe33e3020bbcb4943c55203256dc0bb..f4e0d487f2a9e67e1bdf6acb37610b0bc959a840 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/calculator/SupplierPriceEvalResultCalculator.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/calculator/SupplierPriceEvalResultCalculator.java
@@ -55,7 +55,8 @@ public class SupplierPriceEvalResultCalculator {
 		Objects.requireNonNull(evaluationFactor);
 		
 		this.calcuateFinalScoreFun = FactorUtils.getRealWeight(evaluationFactor.getFactorFinalWeight())::multiply;
-		this.supplierTotalScoreCalculator = SupplierTotalScoreCalculatorFactory.create(PropertiesUtils.getProperty(ConfigConstants.SUPPLIER_TOTAL_SCORE_CALCULATE_TYPE));
+		//this.supplierTotalScoreCalculator = SupplierTotalScoreCalculatorFactory.create(PropertiesUtils.getProperty(ConfigConstants.SUPPLIER_TOTAL_SCORE_CALCULATE_TYPE));
+		this.supplierTotalScoreCalculator = SupplierTotalScoreCalculatorFactory.create(PropertiesUtils.getProperty("SUPPLIER_TOTAL_SCORE_CALCULATE_TYPE找不到"));
 	}
 	
 	/**
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/DefaultPriceEvalStepCreater.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/DefaultPriceEvalStepCreater.java
index d2b29d4b89d1c4b8c2065b42b88488a3f0b88cfc..20f62c3b9a552a8f26adbd740bf2d239f4f28607 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/DefaultPriceEvalStepCreater.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/DefaultPriceEvalStepCreater.java
@@ -1,96 +1,96 @@
-package com.gx.obe.step.price.creater;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import com.gx.obe.components.core.enumeration.CommonEnum;
-import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
-import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
-import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
-import com.gx.obe.datastruct.tree.Forest;
-import com.gx.obe.message.Messages;
-import com.gx.obe.step.price.enums.PriceDetailTableColEnum;
-import com.gx.obe.step.price.utils.FactorUtils;
-import com.gx.obe.util.utils.BigDecimalUtils;
-import com.gx.obe.util.utils.UuidUtils;
-import com.gx.obe.web.entity.evaluation.EvaluationFactor;
-import com.gx.obe.web.entity.evaluation.EvaluationStep;
-
-public class DefaultPriceEvalStepCreater {
-
-	private String tenderId;
-	private Map<Boolean, List<EvaluationFactor>> priceFactorListMap;
-
-	public DefaultPriceEvalStepCreater(String tenderId, List<EvaluationFactor> priceFactorList) {
-		this.tenderId = tenderId;
-		this.priceFactorListMap = new Forest<>(priceFactorList).getLeafList().stream().collect(Collectors.partitioningBy(t -> PriceDetailTableColEnum.contain(t.getBidPriceCode(), PriceDetailTableColEnum.TypeEnum.PRICE)));
-	}
-
-	public List<PriceEvalStep> createSingle() {
-		List<PriceEvalStep> evalStepList = new ArrayList<>();
-		createDetail(evalStepList);
-		List<EvaluationFactor> evaluationFactorList = priceFactorListMap.get(false);
-		if (!evaluationFactorList.isEmpty()) {
-			PriceEvalStep evalStep = create();
-			evalStep.getPriceStep().setStepName(Messages.Step_price);
-			evalStep.getPriceStep().setScore(evaluationFactorList.stream().map(t -> t.getFactorScore()).reduce(null, BigDecimalUtils::add));
-			evalStep.getPriceStep().setWeight(evaluationFactorList.stream().map(this::getPriceStepWeight).reduce(null, BigDecimalUtils::add));
-			evalStep.getPriceStep().setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.PRICE);
-			evalStep.getFactorList().addAll(evaluationFactorList);
-			evalStepList.add(evalStep);
-		}
-		return evalStepList;
-	}
-
-	public List<PriceEvalStep> createMulty() {
-		List<PriceEvalStep> evalStepList = new ArrayList<>();
-		createDetail(evalStepList);
-		for (EvaluationFactor evaluationFactor : priceFactorListMap.get(false)) {
-			PriceEvalStep evalStep = create();
-			evalStep.getPriceStep().setStepName(evaluationFactor.getFactorName());
-			evalStep.getPriceStep().setScore(evaluationFactor.getFactorScore());
-			evalStep.getPriceStep().setWeight(getPriceStepWeight(evaluationFactor));
-			evalStep.getPriceStep().setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.PRICE);
-			evalStep.getFactorList().add(evaluationFactor);
-			evalStepList.add(evalStep);
-		}
-		return evalStepList;
-	}
-
-	private void createDetail(List<PriceEvalStep> evalStepList) {
-		for (EvaluationFactor evaluationFactor : priceFactorListMap.get(true)) {
-			PriceEvalStep evalStep = create();
-			evalStep.getPriceStep().setStepName(evaluationFactor.getFactorName());
-			evalStep.getPriceStep().setScore(evaluationFactor.getFactorScore());
-			evalStep.getPriceStep().setWeight(getPriceStepWeight(evaluationFactor));
-			evalStep.getPriceStep().setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.DETAIL);
-			evalStep.getFactorList().add(evaluationFactor);
-			evalStepList.add(evalStep);
-		}
-	}
-	
-	private PriceEvalStep create() {
-		EvaluationStep priceStep = new EvaluationStep();
-		List<EvaluationFactor> factorList = new ArrayList<>();
-		priceStep.setId(UuidUtils.getUUID());
-		priceStep.setTenderId(tenderId);
-		priceStep.setStepType(EvaluationStepEnum.PRICE);
-		priceStep.setFilterType(EvaluationStepEnum.FILTER_NO);
-		priceStep.setStepStatus(CommonEnum.NOT_START);
-		priceStep.setEvalBidType(EvaluationFactorEnum.EVAL_BID_PRICE);
-		priceStep.setRoleType(EvaluationStepEnum.EXPERT_LEADER);
-		
-		PriceEvalStep priceEvalStep = new PriceEvalStep();
-		priceEvalStep.setPriceStep(priceStep);
-		priceEvalStep.setFactorList(factorList);
-		return priceEvalStep;
-	}
-	
-	private BigDecimal getPriceStepWeight(EvaluationFactor evaluationFactor) {
-		return evaluationFactor.getFactorScore().multiply(FactorUtils.getRealWeight(evaluationFactor.getFactorFinalWeight()));
-	}
-	
-}
+//package com.gx.obe.step.price.creater;
+//
+//import java.math.BigDecimal;
+//import java.util.ArrayList;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.stream.Collectors;
+//
+//import com.gx.obe.components.core.enumeration.CommonEnum;
+//import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+//import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+//import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
+//import com.gx.obe.datastruct.tree.Forest;
+//import com.gx.obe.message.Messages;
+//import com.gx.obe.step.price.enums.PriceDetailTableColEnum;
+//import com.gx.obe.step.price.utils.FactorUtils;
+//import com.gx.obe.util.utils.BigDecimalUtils;
+//import com.gx.obe.util.utils.UuidUtils;
+//import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+//import com.gx.obe.web.entity.evaluation.EvaluationStep;
+//
+//public class DefaultPriceEvalStepCreater {
+//
+//	private String tenderId;
+//	private Map<Boolean, List<EvaluationFactor>> priceFactorListMap;
+//
+//	public DefaultPriceEvalStepCreater(String tenderId, List<EvaluationFactor> priceFactorList) {
+//		this.tenderId = tenderId;
+//		this.priceFactorListMap = new Forest<>(priceFactorList).getLeafList().stream().collect(Collectors.partitioningBy(t -> PriceDetailTableColEnum.contain(t.getBidPriceCode(), PriceDetailTableColEnum.TypeEnum.PRICE)));
+//	}
+//
+//	public List<PriceEvalStep> createSingle() {
+//		List<PriceEvalStep> evalStepList = new ArrayList<>();
+//		createDetail(evalStepList);
+//		List<EvaluationFactor> evaluationFactorList = priceFactorListMap.get(false);
+//		if (!evaluationFactorList.isEmpty()) {
+//			PriceEvalStep evalStep = create();
+//			evalStep.getPriceStep().setStepName(Messages.Step_price);
+//			evalStep.getPriceStep().setScore(evaluationFactorList.stream().map(t -> t.getFactorScore()).reduce(null, BigDecimalUtils::add));
+//			evalStep.getPriceStep().setWeight(evaluationFactorList.stream().map(this::getPriceStepWeight).reduce(null, BigDecimalUtils::add));
+//			evalStep.getPriceStep().setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.PRICE);
+//			evalStep.getFactorList().addAll(evaluationFactorList);
+//			evalStepList.add(evalStep);
+//		}
+//		return evalStepList;
+//	}
+//
+//	public List<PriceEvalStep> createMulty() {
+//		List<PriceEvalStep> evalStepList = new ArrayList<>();
+//		createDetail(evalStepList);
+//		for (EvaluationFactor evaluationFactor : priceFactorListMap.get(false)) {
+//			PriceEvalStep evalStep = create();
+//			evalStep.getPriceStep().setStepName(evaluationFactor.getFactorName());
+//			evalStep.getPriceStep().setScore(evaluationFactor.getFactorScore());
+//			evalStep.getPriceStep().setWeight(getPriceStepWeight(evaluationFactor));
+//			evalStep.getPriceStep().setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.PRICE);
+//			evalStep.getFactorList().add(evaluationFactor);
+//			evalStepList.add(evalStep);
+//		}
+//		return evalStepList;
+//	}
+//
+//	private void createDetail(List<PriceEvalStep> evalStepList) {
+//		for (EvaluationFactor evaluationFactor : priceFactorListMap.get(true)) {
+//			PriceEvalStep evalStep = create();
+//			evalStep.getPriceStep().setStepName(evaluationFactor.getFactorName());
+//			evalStep.getPriceStep().setScore(evaluationFactor.getFactorScore());
+//			evalStep.getPriceStep().setWeight(getPriceStepWeight(evaluationFactor));
+//			evalStep.getPriceStep().setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.DETAIL);
+//			evalStep.getFactorList().add(evaluationFactor);
+//			evalStepList.add(evalStep);
+//		}
+//	}
+//	
+//	private PriceEvalStep create() {
+//		EvaluationStep priceStep = new EvaluationStep();
+//		List<EvaluationFactor> factorList = new ArrayList<>();
+//		priceStep.setId(UuidUtils.getUUID());
+//		priceStep.setTenderId(tenderId);
+//		priceStep.setStepType(EvaluationStepEnum.PRICE);
+//		priceStep.setFilterType(EvaluationStepEnum.FILTER_NO);
+//		priceStep.setStepStatus(CommonEnum.NOT_START);
+//		priceStep.setEvalBidType(EvaluationFactorEnum.EVAL_BID_PRICE);
+//		priceStep.setRoleType(EvaluationStepEnum.EXPERT_LEADER);
+//		
+//		PriceEvalStep priceEvalStep = new PriceEvalStep();
+//		priceEvalStep.setPriceStep(priceStep);
+//		priceEvalStep.setFactorList(factorList);
+//		return priceEvalStep;
+//	}
+//	
+//	private BigDecimal getPriceStepWeight(EvaluationFactor evaluationFactor) {
+//		return evaluationFactor.getFactorScore().multiply(FactorUtils.getRealWeight(evaluationFactor.getFactorFinalWeight()));
+//	}
+//	
+//}
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/PriceEvalStepCreater.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/PriceEvalStepCreater.java
index 0d0b99379f994c2491b815c4812e239c08b361ae..d5f978c4b583550a6b1d238b217aaaf7837e3a1b 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/PriceEvalStepCreater.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/creater/PriceEvalStepCreater.java
@@ -1,110 +1,110 @@
-package com.gx.obe.step.price.creater;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-import com.gx.obe.components.core.enumeration.CommonEnum;
-import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
-import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
-import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
-import com.gx.obe.datastruct.tree.Forest;
-import com.gx.obe.step.price.enums.PriceDetailTableColEnum;
-import com.gx.obe.step.price.utils.FactorUtils;
-import com.gx.obe.util.utils.AssertUtils;
-import com.gx.obe.util.utils.BigDecimalUtils;
-import com.gx.obe.util.utils.UuidUtils;
-import com.gx.obe.web.entity.evaluation.EvaluationFactor;
-import com.gx.obe.web.entity.evaluation.EvaluationStep;
-
-public class PriceEvalStepCreater {
-	
-	private int priceEvalStepCount;
-	
-	private List<EvaluationStep> priceEvalStepList;
-	
-	private List<EvaluationStep> priceDetailEvalStepList;
-	
-	private Map<Boolean, List<EvaluationFactor>> priceFactorListMap;
-	
-	private String tenderId;
-	
-	public PriceEvalStepCreater(String tenderId, List<EvaluationStep> priceStepList, List<EvaluationFactor> factorList) {
-		
-		this.tenderId = tenderId;
-		
-		this.priceEvalStepList = priceStepList.stream().filter(t -> PriceReviewTypeEnum.PRICE.equals(t.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE))).collect(Collectors.toList());
-		
-		this.priceDetailEvalStepList = priceStepList.stream().filter(t -> PriceReviewTypeEnum.DETAIL.equals(t.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE))).collect(Collectors.toList());
-		
-		this.priceFactorListMap = new Forest<>(factorList).getLeafList().stream().collect(Collectors.partitioningBy(t -> PriceDetailTableColEnum.contain(t.getBidPriceCode(), PriceDetailTableColEnum.TypeEnum.PRICE)));
-		
-		this.priceEvalStepCount = priceEvalStepList.size();
-		
-		AssertUtils.isTrue(priceEvalStepCount <= priceFactorListMap.get(false).size());
-		
-		AssertUtils.isTrue(priceDetailEvalStepList.size() == priceFactorListMap.get(true).size());
-	}
-	
-	public PriceEvalStep create(EvaluationStep modelEvaluationStep) {
-		Objects.requireNonNull(modelEvaluationStep);
-		
-		EvaluationStep priceStep = new EvaluationStep();
-		List<EvaluationFactor> factorList = new ArrayList<>();
-		
-		priceStep.setId(UuidUtils.getUUID());
-		
-		String priceReviewType = modelEvaluationStep.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE);
-		if (PriceReviewTypeEnum.PRICE.equals(priceReviewType)) {
-			List<EvaluationFactor> evaluationFactorList;
-			if (priceEvalStepCount == 1) {
-				evaluationFactorList = priceFactorListMap.get(false);
-				priceStep.setStepName(modelEvaluationStep.getStepName());
-			} else {
-				evaluationFactorList = new ArrayList<>();
-				evaluationFactorList.add(priceFactorListMap.get(false).get(0));
-				priceStep.setStepName(evaluationFactorList.get(0).getFactorName());
-			}
-			priceStep.setScore(evaluationFactorList.stream().map(t -> t.getFactorScore()).reduce(null, BigDecimalUtils::add));
-			priceStep.setWeight(evaluationFactorList.stream().map(this::getPriceStepWeight).reduce(null, BigDecimalUtils::add));
-			factorList.addAll(evaluationFactorList);
-			
-			priceEvalStepList.remove(modelEvaluationStep);
-			priceFactorListMap.get(false).removeAll(evaluationFactorList);
-			priceEvalStepCount--;
-		} else if (PriceReviewTypeEnum.DETAIL.equals(priceReviewType)) {
-			EvaluationFactor evaluationFactor = priceFactorListMap.get(true).get(0);
-			
-			priceStep.setStepName(evaluationFactor.getFactorName());
-			priceStep.setScore(evaluationFactor.getFactorScore());
-			priceStep.setWeight(getPriceStepWeight(evaluationFactor));
-			factorList.add(evaluationFactor);
-			
-			priceDetailEvalStepList.remove(modelEvaluationStep);
-			priceFactorListMap.get(true).remove(evaluationFactor);
-		}
-		
-		priceStep.setTenderId(tenderId);
-		priceStep.setStepType(EvaluationStepEnum.PRICE);
-		priceStep.setFilterType(EvaluationStepEnum.FILTER_NO);
-		priceStep.setStepStatus(CommonEnum.NOT_START);
-		priceStep.setEvalBidType(EvaluationFactorEnum.EVAL_BID_PRICE);
-		
-		priceStep.setParams(modelEvaluationStep.getParams());
-		priceStep.setRoleType(modelEvaluationStep.getRoleType());
-		
-		PriceEvalStep priceEvalStep = new PriceEvalStep();
-		priceEvalStep.setPriceStep(priceStep);
-		priceEvalStep.setFactorList(factorList);
-		
-		return priceEvalStep;
-	}
-	
-	private BigDecimal getPriceStepWeight(EvaluationFactor evaluationFactor) {
-		return evaluationFactor.getFactorScore().multiply(FactorUtils.getRealWeight(evaluationFactor.getFactorFinalWeight()));
-	}
-	
-}
+//package com.gx.obe.step.price.creater;
+//
+//import java.math.BigDecimal;
+//import java.util.ArrayList;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Objects;
+//import java.util.stream.Collectors;
+//
+//import com.gx.obe.components.core.enumeration.CommonEnum;
+//import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+//import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+//import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
+//import com.gx.obe.datastruct.tree.Forest;
+//import com.gx.obe.step.price.enums.PriceDetailTableColEnum;
+//import com.gx.obe.step.price.utils.FactorUtils;
+//import com.gx.obe.util.utils.AssertUtils;
+//import com.gx.obe.util.utils.BigDecimalUtils;
+//import com.gx.obe.util.utils.UuidUtils;
+//import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+//import com.gx.obe.web.entity.evaluation.EvaluationStep;
+//
+//public class PriceEvalStepCreater {
+//	
+//	private int priceEvalStepCount;
+//	
+//	private List<EvaluationStep> priceEvalStepList;
+//	
+//	private List<EvaluationStep> priceDetailEvalStepList;
+//	
+//	private Map<Boolean, List<EvaluationFactor>> priceFactorListMap;
+//	
+//	private String tenderId;
+//	
+//	public PriceEvalStepCreater(String tenderId, List<EvaluationStep> priceStepList, List<EvaluationFactor> factorList) {
+//		
+//		this.tenderId = tenderId;
+//		
+//		this.priceEvalStepList = priceStepList.stream().filter(t -> PriceReviewTypeEnum.PRICE.equals(t.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE))).collect(Collectors.toList());
+//		
+//		this.priceDetailEvalStepList = priceStepList.stream().filter(t -> PriceReviewTypeEnum.DETAIL.equals(t.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE))).collect(Collectors.toList());
+//		
+//		this.priceFactorListMap = new Forest<>(factorList).getLeafList().stream().collect(Collectors.partitioningBy(t -> PriceDetailTableColEnum.contain(t.getBidPriceCode(), PriceDetailTableColEnum.TypeEnum.PRICE)));
+//		
+//		this.priceEvalStepCount = priceEvalStepList.size();
+//		
+//		AssertUtils.isTrue(priceEvalStepCount <= priceFactorListMap.get(false).size());
+//		
+//		AssertUtils.isTrue(priceDetailEvalStepList.size() == priceFactorListMap.get(true).size());
+//	}
+//	
+//	public PriceEvalStep create(EvaluationStep modelEvaluationStep) {
+//		Objects.requireNonNull(modelEvaluationStep);
+//		
+//		EvaluationStep priceStep = new EvaluationStep();
+//		List<EvaluationFactor> factorList = new ArrayList<>();
+//		
+//		priceStep.setId(UuidUtils.getUUID());
+//		
+//		String priceReviewType = modelEvaluationStep.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE);
+//		if (PriceReviewTypeEnum.PRICE.equals(priceReviewType)) {
+//			List<EvaluationFactor> evaluationFactorList;
+//			if (priceEvalStepCount == 1) {
+//				evaluationFactorList = priceFactorListMap.get(false);
+//				priceStep.setStepName(modelEvaluationStep.getStepName());
+//			} else {
+//				evaluationFactorList = new ArrayList<>();
+//				evaluationFactorList.add(priceFactorListMap.get(false).get(0));
+//				priceStep.setStepName(evaluationFactorList.get(0).getFactorName());
+//			}
+//			priceStep.setScore(evaluationFactorList.stream().map(t -> t.getFactorScore()).reduce(null, BigDecimalUtils::add));
+//			priceStep.setWeight(evaluationFactorList.stream().map(this::getPriceStepWeight).reduce(null, BigDecimalUtils::add));
+//			factorList.addAll(evaluationFactorList);
+//			
+//			priceEvalStepList.remove(modelEvaluationStep);
+//			priceFactorListMap.get(false).removeAll(evaluationFactorList);
+//			priceEvalStepCount--;
+//		} else if (PriceReviewTypeEnum.DETAIL.equals(priceReviewType)) {
+//			EvaluationFactor evaluationFactor = priceFactorListMap.get(true).get(0);
+//			
+//			priceStep.setStepName(evaluationFactor.getFactorName());
+//			priceStep.setScore(evaluationFactor.getFactorScore());
+//			priceStep.setWeight(getPriceStepWeight(evaluationFactor));
+//			factorList.add(evaluationFactor);
+//			
+//			priceDetailEvalStepList.remove(modelEvaluationStep);
+//			priceFactorListMap.get(true).remove(evaluationFactor);
+//		}
+//		
+//		priceStep.setTenderId(tenderId);
+//		priceStep.setStepType(EvaluationStepEnum.PRICE);
+//		priceStep.setFilterType(EvaluationStepEnum.FILTER_NO);
+//		priceStep.setStepStatus(CommonEnum.NOT_START);
+//		priceStep.setEvalBidType(EvaluationFactorEnum.EVAL_BID_PRICE);
+//		
+//		priceStep.setParams(modelEvaluationStep.getParams());
+//		priceStep.setRoleType(modelEvaluationStep.getRoleType());
+//		
+//		PriceEvalStep priceEvalStep = new PriceEvalStep();
+//		priceEvalStep.setPriceStep(priceStep);
+//		priceEvalStep.setFactorList(factorList);
+//		
+//		return priceEvalStep;
+//	}
+//	
+//	private BigDecimal getPriceStepWeight(EvaluationFactor evaluationFactor) {
+//		return evaluationFactor.getFactorScore().multiply(FactorUtils.getRealWeight(evaluationFactor.getFactorFinalWeight()));
+//	}
+//	
+//}
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/dataset/PriceDetailEvalResultDo.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/dataset/PriceDetailEvalResultDo.java
index 7ef807edf7472cfd8e63324b033b5bbd7b175b91..83c54672e8d93082a91326f110db3b7ca45ccdfd 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/dataset/PriceDetailEvalResultDo.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/dataset/PriceDetailEvalResultDo.java
@@ -1,185 +1,185 @@
-package com.gx.obe.step.price.dataset;
-
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import com.gx.obe.business.entity.SupplierEvaluationStep;
-import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
-import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
-import com.gx.obe.components.core.util.MoneyUtils;
-import com.gx.obe.step.price.beans.PriceDetail;
-import com.gx.obe.step.price.beans.PriceDetailEvalResult;
-import com.gx.obe.step.price.beans.SupplierPriceDetail;
-import com.gx.obe.step.price.beans.SupplierPriceDetailEvalResult;
-import com.gx.obe.step.price.service.PriceDetailEvalResultService;
-import com.gx.obe.step.price.service.PriceDetailService;
-import com.gx.obe.step.price.utils.MapUtils;
-import com.gx.obe.util.utils.CollectionUtils;
-import com.gx.obe.web.entity.Supplier;
-import com.gx.obe.web.entity.evaluation.EvaluationFactor;
-import com.gx.obe.web.entity.evaluation.EvaluationStep;
-import com.gx.obe.web.service.SupplierEvaluationStepService;
-import com.gx.obe.web.service.SupplierService;
-import com.gx.obe.web.service.evaluation.EvaluationFactorService;
-import com.gx.obe.web.service.evaluation.EvaluationStepService;
-
-/**
- * @Description: 价格明细评审结果数据集
- * @author chenxw
- */
-public class PriceDetailEvalResultDo {
-	
-	private final EvaluationStepService evaluationStepService = new EvaluationStepService();
-	private final SupplierService supplierService = new SupplierService();
-	private final SupplierEvaluationStepService supplierEvaluationStepService = new SupplierEvaluationStepService();
-	private final EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
-	
-	private List<SupplierDto> supplierDtoList;
-	private List<PriceDetailDto> priceDetailDtoList;
-	private List<SubCrossData> subCrossDataList;
-	
-	private String tenderId;
-	private String priceUnit;
-	
-	/**
-	 * @author chenxw
-	 * @param tenderId
-	 */
-	public PriceDetailEvalResultDo(String tenderId, String priceUnit) {
-		this.tenderId = tenderId;
-		this.priceUnit = priceUnit;
-		init();
-	}
-	
-	private void init() {
-		List<EvaluationStep> priceEvalStepList = evaluationStepService.getEvaluationStepListByType(tenderId, EvaluationStepEnum.PRICE);
-		if (CollectionUtils.isNull(priceEvalStepList)) {
-			return;
-		}
-		EvaluationStep priceDetailEvalStep = priceEvalStepList.stream().filter(t -> PriceReviewTypeEnum.DETAIL.equals(t.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE))).findAny().orElse(null);
-		if (Objects.isNull(priceDetailEvalStep)) {
-			return;
-		}
-		
-		initSupplierDtoList(priceDetailEvalStep);
-		initPriceDetailEvalResult(priceDetailEvalStep);
-	}
-
-	/**
-	 * @Description: 初始化供应商信息列表
-	 * @author chenxw
-	 * @param tenderId
-	 * @param priceDetailEvalStep
-	 */
-	private void initSupplierDtoList(EvaluationStep priceDetailEvalStep) {
-		List<Supplier> supplierList = supplierService.getEvaluationStepSupplierList(tenderId, priceDetailEvalStep);
-		if (CollectionUtils.isNull(supplierList)) {
-			return;
-		}
-		List<SupplierEvaluationStep> supplierEvaluationStepList = Optional.ofNullable(supplierEvaluationStepService.getSupplierEvaluationStepByTenderIdAndStepId(tenderId, priceDetailEvalStep.getId())).orElseGet(ArrayList::new);
-		Map<String, SupplierEvaluationStep> supplierEvalStepMap = supplierEvaluationStepList.stream().collect(Collectors.toMap(SupplierEvaluationStep::getSupplierId, Function.identity()));
-		supplierDtoList = supplierList.stream().map(t -> {
-			SupplierDto supplierDto = new SupplierDto();
-			supplierDto.setSupplierId(t.getId());
-			supplierDto.setSupplierName(t.getSupplierName());
-			if (supplierEvalStepMap.containsKey(t.getId())) {
-				SupplierEvaluationStep supplierEvalStep = supplierEvalStepMap.get(t.getId());
-				supplierDto.setTotalScore(supplierEvalStep.getEvaluationScore());
-				supplierDto.setSortNo(supplierEvalStep.getSortNo());
-			}
-			return supplierDto;
-		}).collect(Collectors.toList());
-	}
-	
-	/**
-	 * @Description: 初始化报价明细评审结果
-	 * @author chenxw
-	 * @param tenderId
-	 * @param priceDetailEvalStep
-	 */
-	private void initPriceDetailEvalResult(EvaluationStep priceDetailEvalStep) {
-		List<EvaluationFactor> evaluationTopFactorList = evaluationFactorService.getFactorListByStepId(tenderId, priceDetailEvalStep.getId());
-		EvaluationFactor evaluationFactor = Optional.ofNullable(evaluationTopFactorList).map(List::stream).flatMap(Stream::findFirst).orElse(null);
-		if (Objects.isNull(evaluationFactor)) {
-			return;
-		}
-		List<PriceDetail> priceDetailList = PriceDetailService.getPriceDetailList(tenderId, evaluationFactor.getBidPriceCode());
-		if (CollectionUtils.isNull(priceDetailList)) {
-			return;
-		}
-		List<PriceDetailEvalResult> evalResultList = Optional.of(tenderId).map(PriceDetailEvalResultService::getPriceDetailEvalResultList).orElseGet(ArrayList::new);
-		initPriceDetailDtoList(priceDetailList, evalResultList);
-		initSubCrossDataList(priceDetailList, evalResultList);
-	}
-	
-	/**
-	 * @Description: 初始化报价明细信息列表
-	 * @author chenxw
-	 * @param priceDetailList
-	 * @param evalResultList
-	 */
-	private void initPriceDetailDtoList(List<PriceDetail> priceDetailList, List<PriceDetailEvalResult> evalResultList) {
-		Map<String, BigDecimal> priceDetailBasePriceMap = evalResultList.stream().collect(Collectors.toMap(PriceDetailEvalResult::getDetailCode, PriceDetailEvalResult::getBasePrice));
-		priceDetailDtoList = priceDetailList.stream().map(t -> {
-			PriceDetailDto priceDetailDto = new PriceDetailDto();
-			priceDetailDto.setDetailId(t.getDetailCode());
-			priceDetailDto.setDetailCode(t.getDetailCode().trim());
-			if (priceDetailBasePriceMap.containsKey(t.getDetailCode())) {
-				priceDetailDto.setBasePrice(MoneyUtils.getMoneyByUnit(priceDetailBasePriceMap.get(t.getDetailCode()), priceUnit));
-			}
-			return priceDetailDto;
-		}).collect(Collectors.toList());
-	}
-	
-	/**
-	 * @Description: 初始化
-	 * @author chenxw
-	 * @param priceDetailList
-	 * @param evalResultList
-	 */
-	private void initSubCrossDataList(List<PriceDetail> priceDetailList, List<PriceDetailEvalResult> evalResultList) {
-		Map<String, Map<String, BigDecimal>> supplierPriceDetailScoreMapMap = evalResultList.stream().collect(Collectors.toMap(PriceDetailEvalResult::getDetailCode, t -> {
-			return t.getSupplierPriceDetailEvalResultList().stream().collect(Collectors.toMap(SupplierPriceDetailEvalResult::getSupplierId, SupplierPriceDetailEvalResult::getScore));
-		}));
-		subCrossDataList = priceDetailList.stream().flatMap(t -> {
-			List<SupplierPriceDetail> supplierDetailList = t.getSupplierPriceDetailList();
-			if (CollectionUtils.isNull(supplierDetailList)) {
-				return null;
-			}
-			Map<String, BigDecimal> supplierPriceDetailScoreMap = supplierPriceDetailScoreMapMap.get(t.getDetailCode());
-			if (MapUtils.isNull(supplierPriceDetailScoreMap)) {
-				return null;
-			}
-			return supplierDetailList.stream().map(s -> {
-				SubCrossData subCrossData = new SubCrossData();
-				subCrossData.setSupplierId(s.getSupplierId());
-				subCrossData.setDetailId(t.getDetailCode());
-				subCrossData.setPrice(MoneyUtils.getMoneyFromText(s.getEvalPrice(), priceUnit));
-				if (supplierPriceDetailScoreMap.containsKey(s.getSupplierId())) {
-					subCrossData.setScore(supplierPriceDetailScoreMap.get(s.getSupplierId()));
-				}
-				return subCrossData;
-			});
-		}).collect(Collectors.toList());
-	}
-
-	public List<SupplierDto> getSupplierDtoList() {
-		return supplierDtoList;
-	}
-
-	public List<PriceDetailDto> getPriceDetailDtoList() {
-		return priceDetailDtoList;
-	}
-
-	public List<SubCrossData> getSubCrossDataList() {
-		return subCrossDataList;
-	}
-	
-}
+//package com.gx.obe.step.price.dataset;
+//
+//import java.math.BigDecimal;
+//import java.util.ArrayList;
+//import java.util.List;
+//import java.util.Map;
+//import java.util.Objects;
+//import java.util.Optional;
+//import java.util.function.Function;
+//import java.util.stream.Collectors;
+//import java.util.stream.Stream;
+//
+//import com.gx.obe.business.entity.SupplierEvaluationStep;
+//import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+//import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
+//import com.gx.obe.components.core.util.MoneyUtils;
+//import com.gx.obe.step.price.beans.PriceDetail;
+//import com.gx.obe.step.price.beans.PriceDetailEvalResult;
+//import com.gx.obe.step.price.beans.SupplierPriceDetail;
+//import com.gx.obe.step.price.beans.SupplierPriceDetailEvalResult;
+//import com.gx.obe.step.price.service.PriceDetailEvalResultService;
+//import com.gx.obe.step.price.service.PriceDetailService;
+//import com.gx.obe.step.price.utils.MapUtils;
+//import com.gx.obe.util.utils.CollectionUtils;
+//import com.gx.obe.web.entity.Supplier;
+//import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+//import com.gx.obe.web.entity.evaluation.EvaluationStep;
+//import com.gx.obe.web.service.SupplierEvaluationStepService;
+//import com.gx.obe.web.service.SupplierService;
+//import com.gx.obe.web.service.evaluation.EvaluationFactorService;
+//import com.gx.obe.web.service.evaluation.EvaluationStepService;
+//
+///**
+// * @Description: 价格明细评审结果数据集
+// * @author chenxw
+// */
+//public class PriceDetailEvalResultDo {
+//	
+//	private final EvaluationStepService evaluationStepService = new EvaluationStepService();
+//	private final SupplierService supplierService = new SupplierService();
+//	private final SupplierEvaluationStepService supplierEvaluationStepService = new SupplierEvaluationStepService();
+//	private final EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
+//	
+//	private List<SupplierDto> supplierDtoList;
+//	private List<PriceDetailDto> priceDetailDtoList;
+//	private List<SubCrossData> subCrossDataList;
+//	
+//	private String tenderId;
+//	private String priceUnit;
+//	
+//	/**
+//	 * @author chenxw
+//	 * @param tenderId
+//	 */
+//	public PriceDetailEvalResultDo(String tenderId, String priceUnit) {
+//		this.tenderId = tenderId;
+//		this.priceUnit = priceUnit;
+//		init();
+//	}
+//	
+//	private void init() {
+//		List<EvaluationStep> priceEvalStepList = evaluationStepService.getEvaluationStepListByType(tenderId, EvaluationStepEnum.PRICE);
+//		if (CollectionUtils.isNull(priceEvalStepList)) {
+//			return;
+//		}
+//		EvaluationStep priceDetailEvalStep = priceEvalStepList.stream().filter(t -> PriceReviewTypeEnum.DETAIL.equals(t.getEvaluationParamByKey(EvaluationStepEnum.PRICE_REVIEW_TYPE))).findAny().orElse(null);
+//		if (Objects.isNull(priceDetailEvalStep)) {
+//			return;
+//		}
+//		
+//		initSupplierDtoList(priceDetailEvalStep);
+//		initPriceDetailEvalResult(priceDetailEvalStep);
+//	}
+//
+//	/**
+//	 * @Description: 初始化供应商信息列表
+//	 * @author chenxw
+//	 * @param tenderId
+//	 * @param priceDetailEvalStep
+//	 */
+//	private void initSupplierDtoList(EvaluationStep priceDetailEvalStep) {
+//		List<Supplier> supplierList = supplierService.getEvaluationStepSupplierList(tenderId, priceDetailEvalStep);
+//		if (CollectionUtils.isNull(supplierList)) {
+//			return;
+//		}
+//		List<SupplierEvaluationStep> supplierEvaluationStepList = Optional.ofNullable(supplierEvaluationStepService.getSupplierEvaluationStepByTenderIdAndStepId(tenderId, priceDetailEvalStep.getId())).orElseGet(ArrayList::new);
+//		Map<String, SupplierEvaluationStep> supplierEvalStepMap = supplierEvaluationStepList.stream().collect(Collectors.toMap(SupplierEvaluationStep::getSupplierId, Function.identity()));
+//		supplierDtoList = supplierList.stream().map(t -> {
+//			SupplierDto supplierDto = new SupplierDto();
+//			supplierDto.setSupplierId(t.getId());
+//			supplierDto.setSupplierName(t.getSupplierName());
+//			if (supplierEvalStepMap.containsKey(t.getId())) {
+//				SupplierEvaluationStep supplierEvalStep = supplierEvalStepMap.get(t.getId());
+//				supplierDto.setTotalScore(supplierEvalStep.getEvaluationScore());
+//				supplierDto.setSortNo(supplierEvalStep.getSortNo());
+//			}
+//			return supplierDto;
+//		}).collect(Collectors.toList());
+//	}
+//	
+//	/**
+//	 * @Description: 初始化报价明细评审结果
+//	 * @author chenxw
+//	 * @param tenderId
+//	 * @param priceDetailEvalStep
+//	 */
+//	private void initPriceDetailEvalResult(EvaluationStep priceDetailEvalStep) {
+//		List<EvaluationFactor> evaluationTopFactorList = evaluationFactorService.getFactorListByStepId(tenderId, priceDetailEvalStep.getId());
+//		EvaluationFactor evaluationFactor = Optional.ofNullable(evaluationTopFactorList).map(List::stream).flatMap(Stream::findFirst).orElse(null);
+//		if (Objects.isNull(evaluationFactor)) {
+//			return;
+//		}
+//		List<PriceDetail> priceDetailList = PriceDetailService.getPriceDetailList(tenderId, evaluationFactor.getBidPriceCode());
+//		if (CollectionUtils.isNull(priceDetailList)) {
+//			return;
+//		}
+//		List<PriceDetailEvalResult> evalResultList = Optional.of(tenderId).map(PriceDetailEvalResultService::getPriceDetailEvalResultList).orElseGet(ArrayList::new);
+//		initPriceDetailDtoList(priceDetailList, evalResultList);
+//		initSubCrossDataList(priceDetailList, evalResultList);
+//	}
+//	
+//	/**
+//	 * @Description: 初始化报价明细信息列表
+//	 * @author chenxw
+//	 * @param priceDetailList
+//	 * @param evalResultList
+//	 */
+//	private void initPriceDetailDtoList(List<PriceDetail> priceDetailList, List<PriceDetailEvalResult> evalResultList) {
+//		Map<String, BigDecimal> priceDetailBasePriceMap = evalResultList.stream().collect(Collectors.toMap(PriceDetailEvalResult::getDetailCode, PriceDetailEvalResult::getBasePrice));
+//		priceDetailDtoList = priceDetailList.stream().map(t -> {
+//			PriceDetailDto priceDetailDto = new PriceDetailDto();
+//			priceDetailDto.setDetailId(t.getDetailCode());
+//			priceDetailDto.setDetailCode(t.getDetailCode().trim());
+//			if (priceDetailBasePriceMap.containsKey(t.getDetailCode())) {
+//				priceDetailDto.setBasePrice(MoneyUtils.getMoneyByUnit(priceDetailBasePriceMap.get(t.getDetailCode()), priceUnit));
+//			}
+//			return priceDetailDto;
+//		}).collect(Collectors.toList());
+//	}
+//	
+//	/**
+//	 * @Description: 初始化
+//	 * @author chenxw
+//	 * @param priceDetailList
+//	 * @param evalResultList
+//	 */
+//	private void initSubCrossDataList(List<PriceDetail> priceDetailList, List<PriceDetailEvalResult> evalResultList) {
+//		Map<String, Map<String, BigDecimal>> supplierPriceDetailScoreMapMap = evalResultList.stream().collect(Collectors.toMap(PriceDetailEvalResult::getDetailCode, t -> {
+//			return t.getSupplierPriceDetailEvalResultList().stream().collect(Collectors.toMap(SupplierPriceDetailEvalResult::getSupplierId, SupplierPriceDetailEvalResult::getScore));
+//		}));
+//		subCrossDataList = priceDetailList.stream().flatMap(t -> {
+//			List<SupplierPriceDetail> supplierDetailList = t.getSupplierPriceDetailList();
+//			if (CollectionUtils.isNull(supplierDetailList)) {
+//				return null;
+//			}
+//			Map<String, BigDecimal> supplierPriceDetailScoreMap = supplierPriceDetailScoreMapMap.get(t.getDetailCode());
+//			if (MapUtils.isNull(supplierPriceDetailScoreMap)) {
+//				return null;
+//			}
+//			return supplierDetailList.stream().map(s -> {
+//				SubCrossData subCrossData = new SubCrossData();
+//				subCrossData.setSupplierId(s.getSupplierId());
+//				subCrossData.setDetailId(t.getDetailCode());
+//				subCrossData.setPrice(MoneyUtils.getMoneyFromText(s.getEvalPrice(), priceUnit));
+//				if (supplierPriceDetailScoreMap.containsKey(s.getSupplierId())) {
+//					subCrossData.setScore(supplierPriceDetailScoreMap.get(s.getSupplierId()));
+//				}
+//				return subCrossData;
+//			});
+//		}).collect(Collectors.toList());
+//	}
+//
+//	public List<SupplierDto> getSupplierDtoList() {
+//		return supplierDtoList;
+//	}
+//
+//	public List<PriceDetailDto> getPriceDetailDtoList() {
+//		return priceDetailDtoList;
+//	}
+//
+//	public List<SubCrossData> getSubCrossDataList() {
+//		return subCrossDataList;
+//	}
+//	
+//}
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/dialog/PriceDetailEvaluationStepDialog.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/dialog/PriceDetailEvaluationStepDialog.java
index 20dfd60754275720523f28b0bec3c57814a389bc..44027b0da565b6938c9b447e7fe2a449bc8ca814 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/dialog/PriceDetailEvaluationStepDialog.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/dialog/PriceDetailEvaluationStepDialog.java
@@ -1,191 +1,191 @@
-package com.gx.obe.step.price.dialog;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Predicate;
-
-import org.eclipse.nebula.widgets.grid.Grid;
-import org.eclipse.nebula.widgets.grid.GridColumn;
-import org.eclipse.nebula.widgets.grid.GridItem;
-import org.eclipse.nebula.widgets.grid.listener.GridCheckedListener;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.core.ImageResolver;
-import org.eclipse.swt.core.utils.GridUtils;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Shell;
-
-import com.gx.obe.common.icons.IconsActivator;
-import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
-import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
-import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
-import com.gx.obe.datastruct.tree.Forest;
-import com.gx.obe.step.dialog.EvaluationStepSingleDialog;
-import com.gx.obe.step.price.utils.FactorUtils;
-import com.gx.obe.step.price.utils.IPriceEvalStep;
-import com.gx.obe.util.utils.CollectionUtils;
-import com.gx.obe.util.utils.PredicateUtils;
-import com.gx.obe.web.entity.evaluation.EvaluationFactor;
-import com.gx.obe.web.entity.evaluation.EvaluationStep;
-import com.gx.obe.web.entity.tender.TenderProjectEntity;
-import com.gx.obe.web.service.evaluation.EvaluationFactorService;
-
-/**
- * @Description: 价格明细评审步骤界面
- * @author chenxw
- */
-public class PriceDetailEvaluationStepDialog extends EvaluationStepSingleDialog implements IPriceEvalStep {
-	
-	private final String FACTOR_DATA = "evaluationFactor";
-	
-	private final EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
-	
-	private final Image treeExpandPic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_expend.png");
-	private final Image treeClosePic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_close.png");
-	
-	private final Image treeParentPic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_parent.png");
-	private final Image treeItemPic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_item.png");
-	
-	private Grid factorGrid;
-	
-	/**
-	 * @author chenxw
-	 * @param parentShell
-	 * @param tenderProject
-	 * @param evaluationStep
-	 */
-	public PriceDetailEvaluationStepDialog(Shell parentShell, TenderProjectEntity tenderProject, EvaluationStep evaluationStep) {
-		super(parentShell, tenderProject, evaluationStep);
-	}
-	
-	@Override
-	protected String getTipsText() {
-		return "自动计算价格明细得分";
-	}
-	
-	@Override
-	protected String getStepNameDef() {
-		return "价格明细评审";
-	}
-	
-	@Override
-	protected String getStepType() {
-		return EvaluationStepEnum.PRICE;
-	}
-	
-	@Override
-	protected void createFromArea(Composite fromComposite, Composite gridComposite) {
-		super.createFromArea(fromComposite, gridComposite);
-		
-		Composite composite = new Composite(gridComposite, SWT.NONE);
-		GridLayout gl_composite = new GridLayout(1, false);
-		gl_composite.marginHeight = 0;
-		gl_composite.marginWidth = 0;
-		composite.setLayout(gl_composite);
-		
-		factorGrid = new Grid(composite, SWT.NONE);
-		GridData gd_composite_1 = new GridData(SWT.CENTER, SWT.FILL, false, true, 1, 1);
-		gd_composite_1.widthHint = 200;
-		factorGrid.setLayoutData(gd_composite_1);
-		factorGrid.addListener(SWT.Selection, new GridCheckedListener(false));
-		
-		GridColumn gridColumn = new GridColumn(factorGrid, SWT.CHECK);
-		gridColumn.setWidth(200);
-		gridColumn.setWordWrap(true);
-		gridColumn.setTree(true);
-		gridColumn.setShowTreeTogglePic(true);
-		gridColumn.setTreeTogglePic(treeExpandPic, treeClosePic);
-		
-		initFactorGrid();
-	}
-	
-	/**
-	 * @Description: 初始化指标表格界面
-	 * @author chenxw
-	 */
-	private void initFactorGrid() {
-		List<EvaluationFactor> evaluationFactorList = evaluationFactorService.getAllEvaluationFactorList(tenderProject.getId(), EvaluationFactorEnum.AUDIT_PRICE);
-		if (CollectionUtils.isNull(evaluationFactorList)) {
-			return;
-		}
-		Forest<EvaluationFactor> factorForest = new Forest<>(evaluationFactorList);
-		
-		filterForestByStepFactor(tenderProject, evaluationStep, factorForest);
-		IPriceEvalStep.filterForestByReviewType(factorForest, PriceReviewTypeEnum.DETAIL);
-		
-		for (EvaluationFactor evaluationFactor : evaluationFactorList) {
-			initFactorGridItem(new GridItem(factorGrid, SWT.NONE), evaluationFactor);
-		}
-	}
-	
-	/**
-	 * @Description: 初始化指标表格行
-	 * @author chenxw
-	 * @param parentItem
-	 * @param evaluationFactor 
-	 */
-	private void initFactorGridItem(GridItem parentItem, EvaluationFactor evaluationFactor) {
-		parentItem.setText(evaluationFactor.getFactorName());
-		List<EvaluationFactor> childFactorList = evaluationFactor.getChildFactorList();
-		if (CollectionUtils.isNull(childFactorList)) {
-			parentItem.setImage(treeItemPic);
-			parentItem.setData(FACTOR_DATA, evaluationFactor);
-			return;
-		}
-		parentItem.setExpanded(true);
-		parentItem.setCheckVisible(0, false);
-		parentItem.setImage(treeParentPic);
-		for (EvaluationFactor childFactor : childFactorList) {
-			initFactorGridItem(new GridItem(parentItem, SWT.NONE), childFactor);
-		}
-	}
-	
-	@Override
-	protected void setFromData(EvaluationStep evaluationStep) {
-		super.setFromData(evaluationStep);
-		
-		List<Object> factorIdList = evaluationStepFactorService.getFactorIdLsitByStepId(evaluationStep.getId());
-		Predicate<GridItem> gridItemPre = PredicateUtils.map(this::getFactorIdByItem, factorIdList::contains);
-		Arrays.stream(factorGrid.getItems()).filter(gridItemPre).forEach(t -> t.setChecked(true));
-	}
-	
-	/**
-	 * @Description: 根据表格行获取指标id
-	 * @author chenxw
-	 * @param item
-	 * @return 
-	 */
-	private String getFactorIdByItem(GridItem item) {
-		return Optional.ofNullable(item).map(t -> (EvaluationFactor) t.getData(FACTOR_DATA)).map(EvaluationFactor::getId).orElse(null);
-	}
-	
-	@Override
-	protected String valFromData() {
-		List<EvaluationFactor> checkedFactorList = GridUtils.getCheckedValues(factorGrid, 0, FACTOR_DATA, true);
-		if (CollectionUtils.isNull(checkedFactorList)) return "请选择评审指标!";
-		if (checkedFactorList.size() > 1) return "价格明细评审步骤只能选择一个价格明细指标!";
-		return null;
-	}
-	
-	@Override
-	protected void getFromData(EvaluationStep evaluationStep) {
-		super.getFromData(evaluationStep);
-		
-		List<EvaluationFactor> checkedFactorList = GridUtils.getCheckedValues(factorGrid, 0, FACTOR_DATA, true);
-		EvaluationFactor evaluationFactor = checkedFactorList.get(0);
-		addEvaluationFactor(evaluationFactor);
-		evaluationStep.setScore(evaluationFactor.getFactorScore());
-		evaluationStep.setWeight(evaluationFactor.getFactorScore().multiply(FactorUtils.getRealWeight(evaluationFactor.getFactorFinalWeight())));
-		evaluationStep.setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.DETAIL);
-	}
-	
-	@Override
-	protected Point getInitialSize() {
-		return new Point(600, 350);
-	}
-	
-}
+//package com.gx.obe.step.price.dialog;
+//
+//import java.util.Arrays;
+//import java.util.List;
+//import java.util.Optional;
+//import java.util.function.Predicate;
+//
+//import org.eclipse.nebula.widgets.grid.Grid;
+//import org.eclipse.nebula.widgets.grid.GridColumn;
+//import org.eclipse.nebula.widgets.grid.GridItem;
+//import org.eclipse.nebula.widgets.grid.listener.GridCheckedListener;
+//import org.eclipse.swt.SWT;
+//import org.eclipse.swt.core.ImageResolver;
+//import org.eclipse.swt.core.utils.GridUtils;
+//import org.eclipse.swt.graphics.Image;
+//import org.eclipse.swt.graphics.Point;
+//import org.eclipse.swt.layout.GridData;
+//import org.eclipse.swt.layout.GridLayout;
+//import org.eclipse.swt.widgets.Composite;
+//import org.eclipse.swt.widgets.Shell;
+//
+//import com.gx.obe.common.icons.IconsActivator;
+//import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+//import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+//import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
+//import com.gx.obe.datastruct.tree.Forest;
+//import com.gx.obe.step.dialog.EvaluationStepSingleDialog;
+//import com.gx.obe.step.price.utils.FactorUtils;
+//import com.gx.obe.step.price.utils.IPriceEvalStep;
+//import com.gx.obe.util.utils.CollectionUtils;
+//import com.gx.obe.util.utils.PredicateUtils;
+//import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+//import com.gx.obe.web.entity.evaluation.EvaluationStep;
+//import com.gx.obe.web.entity.tender.TenderProjectEntity;
+//import com.gx.obe.web.service.evaluation.EvaluationFactorService;
+//
+///**
+// * @Description: 价格明细评审步骤界面
+// * @author chenxw
+// */
+//public class PriceDetailEvaluationStepDialog extends EvaluationStepSingleDialog implements IPriceEvalStep {
+//	
+//	private final String FACTOR_DATA = "evaluationFactor";
+//	
+//	private final EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
+//	
+//	private final Image treeExpandPic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_expend.png");
+//	private final Image treeClosePic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_close.png");
+//	
+//	private final Image treeParentPic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_parent.png");
+//	private final Image treeItemPic = ImageResolver.RESOLVER_INSTANCE.loadImage(IconsActivator.PLUGIN_ID, "icons/tree_item.png");
+//	
+//	private Grid factorGrid;
+//	
+//	/**
+//	 * @author chenxw
+//	 * @param parentShell
+//	 * @param tenderProject
+//	 * @param evaluationStep
+//	 */
+//	public PriceDetailEvaluationStepDialog(Shell parentShell, TenderProjectEntity tenderProject, EvaluationStep evaluationStep) {
+//		super(parentShell, tenderProject, evaluationStep);
+//	}
+//	
+//	@Override
+//	protected String getTipsText() {
+//		return "自动计算价格明细得分";
+//	}
+//	
+//	@Override
+//	protected String getStepNameDef() {
+//		return "价格明细评审";
+//	}
+//	
+//	@Override
+//	protected String getStepType() {
+//		return EvaluationStepEnum.PRICE;
+//	}
+//	
+//	@Override
+//	protected void createFromArea(Composite fromComposite, Composite gridComposite) {
+//		super.createFromArea(fromComposite, gridComposite);
+//		
+//		Composite composite = new Composite(gridComposite, SWT.NONE);
+//		GridLayout gl_composite = new GridLayout(1, false);
+//		gl_composite.marginHeight = 0;
+//		gl_composite.marginWidth = 0;
+//		composite.setLayout(gl_composite);
+//		
+//		factorGrid = new Grid(composite, SWT.NONE);
+//		GridData gd_composite_1 = new GridData(SWT.CENTER, SWT.FILL, false, true, 1, 1);
+//		gd_composite_1.widthHint = 200;
+//		factorGrid.setLayoutData(gd_composite_1);
+//		factorGrid.addListener(SWT.Selection, new GridCheckedListener(false));
+//		
+//		GridColumn gridColumn = new GridColumn(factorGrid, SWT.CHECK);
+//		gridColumn.setWidth(200);
+//		gridColumn.setWordWrap(true);
+//		gridColumn.setTree(true);
+//		gridColumn.setShowTreeTogglePic(true);
+//		gridColumn.setTreeTogglePic(treeExpandPic, treeClosePic);
+//		
+//		initFactorGrid();
+//	}
+//	
+//	/**
+//	 * @Description: 初始化指标表格界面
+//	 * @author chenxw
+//	 */
+//	private void initFactorGrid() {
+//		List<EvaluationFactor> evaluationFactorList = evaluationFactorService.getAllEvaluationFactorList(tenderProject.getId(), EvaluationFactorEnum.AUDIT_PRICE);
+//		if (CollectionUtils.isNull(evaluationFactorList)) {
+//			return;
+//		}
+//		Forest<EvaluationFactor> factorForest = new Forest<>(evaluationFactorList);
+//		
+//		filterForestByStepFactor(tenderProject, evaluationStep, factorForest);
+//		IPriceEvalStep.filterForestByReviewType(factorForest, PriceReviewTypeEnum.DETAIL);
+//		
+//		for (EvaluationFactor evaluationFactor : evaluationFactorList) {
+//			initFactorGridItem(new GridItem(factorGrid, SWT.NONE), evaluationFactor);
+//		}
+//	}
+//	
+//	/**
+//	 * @Description: 初始化指标表格行
+//	 * @author chenxw
+//	 * @param parentItem
+//	 * @param evaluationFactor 
+//	 */
+//	private void initFactorGridItem(GridItem parentItem, EvaluationFactor evaluationFactor) {
+//		parentItem.setText(evaluationFactor.getFactorName());
+//		List<EvaluationFactor> childFactorList = evaluationFactor.getChildFactorList();
+//		if (CollectionUtils.isNull(childFactorList)) {
+//			parentItem.setImage(treeItemPic);
+//			parentItem.setData(FACTOR_DATA, evaluationFactor);
+//			return;
+//		}
+//		parentItem.setExpanded(true);
+//		parentItem.setCheckVisible(0, false);
+//		parentItem.setImage(treeParentPic);
+//		for (EvaluationFactor childFactor : childFactorList) {
+//			initFactorGridItem(new GridItem(parentItem, SWT.NONE), childFactor);
+//		}
+//	}
+//	
+//	@Override
+//	protected void setFromData(EvaluationStep evaluationStep) {
+//		super.setFromData(evaluationStep);
+//		
+//		List<Object> factorIdList = evaluationStepFactorService.getFactorIdLsitByStepId(evaluationStep.getId());
+//		Predicate<GridItem> gridItemPre = PredicateUtils.map(this::getFactorIdByItem, factorIdList::contains);
+//		Arrays.stream(factorGrid.getItems()).filter(gridItemPre).forEach(t -> t.setChecked(true));
+//	}
+//	
+//	/**
+//	 * @Description: 根据表格行获取指标id
+//	 * @author chenxw
+//	 * @param item
+//	 * @return 
+//	 */
+//	private String getFactorIdByItem(GridItem item) {
+//		return Optional.ofNullable(item).map(t -> (EvaluationFactor) t.getData(FACTOR_DATA)).map(EvaluationFactor::getId).orElse(null);
+//	}
+//	
+//	@Override
+//	protected String valFromData() {
+//		List<EvaluationFactor> checkedFactorList = GridUtils.getCheckedValues(factorGrid, 0, FACTOR_DATA, true);
+//		if (CollectionUtils.isNull(checkedFactorList)) return "请选择评审指标!";
+//		if (checkedFactorList.size() > 1) return "价格明细评审步骤只能选择一个价格明细指标!";
+//		return null;
+//	}
+//	
+//	@Override
+//	protected void getFromData(EvaluationStep evaluationStep) {
+//		super.getFromData(evaluationStep);
+//		
+//		List<EvaluationFactor> checkedFactorList = GridUtils.getCheckedValues(factorGrid, 0, FACTOR_DATA, true);
+//		EvaluationFactor evaluationFactor = checkedFactorList.get(0);
+//		addEvaluationFactor(evaluationFactor);
+//		evaluationStep.setScore(evaluationFactor.getFactorScore());
+//		evaluationStep.setWeight(evaluationFactor.getFactorScore().multiply(FactorUtils.getRealWeight(evaluationFactor.getFactorFinalWeight())));
+//		evaluationStep.setEvaluationParam(EvaluationStepEnum.PRICE_REVIEW_TYPE, PriceReviewTypeEnum.DETAIL);
+//	}
+//	
+//	@Override
+//	protected Point getInitialSize() {
+//		return new Point(600, 350);
+//	}
+//	
+//}
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/enums/PriceDetailTableColEnum.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/enums/PriceDetailTableColEnum.java
index e674811f335d071a4632cf6a7463ef0bf1f3a133..4e0aeefb5e103f5046e59bd589b76c996fdd2b11 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/enums/PriceDetailTableColEnum.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/enums/PriceDetailTableColEnum.java
@@ -57,7 +57,9 @@ public enum PriceDetailTableColEnum {
 	/**
 	 * @Description: keyMap
 	 */
-	public static Map<String, PriceDetailTableColEnum> PRICE_MAP = EnumUtils.toMap(values(), PriceDetailTableColEnum::getKey, PredicateUtils.map(PriceDetailTableColEnum::getTypeEnum, Predicate.isEqual(TypeEnum.PRICE)));
+	//public static Map<String, PriceDetailTableColEnum> PRICE_MAP = EnumUtils.toMap(values(), PriceDetailTableColEnum::getKey, PredicateUtils.map(PriceDetailTableColEnum::getTypeEnum, Predicate.isEqual(TypeEnum.PRICE)));
+	//类缺少内容
+	public static Map<String, PriceDetailTableColEnum> PRICE_MAP = new HashMap<String,PriceDetailTableColEnum>();
 	
 	/**
 	 * @Description: key列表缓存
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/table/SupplierTreeTable.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/table/SupplierTreeTable.java
index e0b949c01cadd2f7f38480e3e292f634c41865d5..a37af8dc6834e2152fd169ee36fc63bce8c6a476 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/table/SupplierTreeTable.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/table/SupplierTreeTable.java
@@ -119,14 +119,16 @@ public class SupplierTreeTable extends KTable {
 	private void initTableRowCol() {
 		tableColList.add(new TableCol("序号", i -> String.valueOf(i + 1)));
 		
-		String type = PropertiesUtils.getProperty(ConfigConstants.SHOW_PRICE_DETAIL_COL_CONTENT_TYPE);
+		//String type = PropertiesUtils.getProperty(ConfigConstants.SHOW_PRICE_DETAIL_COL_CONTENT_TYPE);
+		String type = PropertiesUtils.getProperty("");
 		Function<Integer, PriceDetail> getPriceDetailByIndex = priceDetailList::get;
 		tableColList.add(new TableCol("报价明细", getPriceDetailByIndex.andThen(priceDetailColContentFun(type)).andThen(ObjectUtils::getObjString)));
 		
 		Function<String, BigDecimal> basePriceFun = evalResultList.stream().collect(Collectors.toMap(PriceDetailEvalResult::getDetailCode, PriceDetailEvalResult::getBasePrice))::get;
 		tableColList.add(new TableCol("基准价(" + projectRule.getPriceUnit() + ")", getPriceDetailByIndex.andThen(PriceDetail::getDetailCode).andThen(basePriceFun).andThen(this::formatPrice)));
 		
-		if (PropertiesUtils.getProperty(ConfigConstants.SUPPLIER_TREE_TABLE_SHOW_WEIGHT, CommonEnum.NO).equals(CommonEnum.YES))
+		//if (PropertiesUtils.getProperty(ConfigConstants.SUPPLIER_TREE_TABLE_SHOW_WEIGHT, CommonEnum.NO).equals(CommonEnum.YES))
+		if (PropertiesUtils.getProperty(CommonEnum.NO, CommonEnum.NO).equals(CommonEnum.YES))
 			tableColList.add(new TableCol("权重(%)", getPriceDetailByIndex.andThen(PriceDetail::getScoreWeight).andThen(ObjectUtils::getObjString)));
 		
 		Function<Object, EvaluationFactorResult> evaluationFactorResultFun = factorResultList.stream().collect(Collectors.toMap(EvaluationFactorResult::getSupplierId, Function.identity()))::get;
diff --git a/com.gx.obe.step.price/src/com/gx/obe/step/price/utils/IPriceEvalStep.java b/com.gx.obe.step.price/src/com/gx/obe/step/price/utils/IPriceEvalStep.java
index a4c5ce9ab2439c894a8772d8004236560bb04a88..3f9b44b435f462fec119d7cf098b94164b9fac34 100644
--- a/com.gx.obe.step.price/src/com/gx/obe/step/price/utils/IPriceEvalStep.java
+++ b/com.gx.obe.step.price/src/com/gx/obe/step/price/utils/IPriceEvalStep.java
@@ -1,83 +1,85 @@
-package com.gx.obe.step.price.utils;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import com.gx.obe.business.entity.EvaluationStepFactor;
-import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
-import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
-import com.gx.obe.datastruct.tree.Forest;
-import com.gx.obe.step.price.enums.PriceDetailTableColEnum;
-import com.gx.obe.step.service.StepFactorService;
-import com.gx.obe.util.utils.CollectionUtils;
-import com.gx.obe.util.utils.PredicateUtils;
-import com.gx.obe.web.entity.evaluation.EvaluationFactor;
-import com.gx.obe.web.entity.evaluation.EvaluationStep;
-import com.gx.obe.web.entity.tender.TenderProjectEntity;
-import com.gx.obe.web.service.evaluation.EvaluationFactorService;
-import com.gx.obe.web.service.evaluation.EvaluationStepFactorService;
-
-public interface IPriceEvalStep {
-	
-	EvaluationStepFactorService evaluationStepFactorService = new EvaluationStepFactorService();
-	EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
-	
-	boolean isAdd();
-	
-	/**
-	 * @Description: 根据步骤绑定的指标过滤指标树
-	 * @author chenxw
-	 * @param factorForest
-	 */
-	default void filterForestByStepFactor(TenderProjectEntity tenderProject, EvaluationStep evaluationStep, Forest<EvaluationFactor> factorForest) {
-		List<EvaluationStepFactor> evaluationStepFactorList = StepFactorService.getListByAuditType(tenderProject.getId(), EvaluationFactorEnum.AUDIT_PRICE);
-		if (CollectionUtils.isNull(evaluationStepFactorList)) {
-			return;
-		}
-		Stream<String> factorIdStream = evaluationStepFactorList.stream().map(EvaluationStepFactor::getFactorId);
-		if (!this.isAdd()) {
-			List<Object> factorIdLsitByStepId = evaluationStepFactorService.getFactorIdLsitByStepId(evaluationStep.getId());
-			factorIdStream = factorIdStream.filter(t -> !factorIdLsitByStepId.contains(t));
-		}
-		List<String> factorIdList = factorIdStream.collect(Collectors.toList());
-		factorForest.filterPath(t -> !factorIdList.contains(t.getId()));
-	}
-	
-	static boolean isCreatePriceStep(TenderProjectEntity tenderProject, List<EvaluationStepFactor> evaluationStepFactorList, String priceReviewType) {
-		List<EvaluationFactor> priceEvalFactorList = evaluationFactorService.getAllEvaluationFactorList(tenderProject.getId(), EvaluationFactorEnum.AUDIT_PRICE);
-		if (CollectionUtils.isNull(priceEvalFactorList)) {
-			return false;
-		}
-		List<EvaluationFactor> list = new ArrayList<>(priceEvalFactorList);
-		Forest<EvaluationFactor> factorForest = new Forest<>(list);
-		if (CollectionUtils.isNotNull(evaluationStepFactorList)) {
-			List<String> factorIdList = evaluationStepFactorList.stream().map(EvaluationStepFactor::getFactorId).collect(Collectors.toList());
-			factorForest.filterPath(t -> !factorIdList.contains(t.getId()));
-		}
-		IPriceEvalStep.filterForestByReviewType(factorForest, priceReviewType);
-		return !list.isEmpty();
-	}
-	
-	/**
-	 * @Description: 根据价格步骤的评审类型过滤指标树
-	 * @author chenxw
-	 * @param factorForest
-	 */
-	static void filterForestByReviewType(Forest<EvaluationFactor> factorForest, String priceReviewType) {
-		factorForest.filterPath(PredicateUtils.map(EvaluationFactor::getBidPriceCode, getBidPriceCodePredicate(priceReviewType)));
-	}
-
-	static Predicate<String> getBidPriceCodePredicate(String priceReviewType) {
-		switch (priceReviewType) {
-			case PriceReviewTypeEnum.PRICE:
-				return t -> !PriceDetailTableColEnum.contain(t, PriceDetailTableColEnum.TypeEnum.PRICE);
-			case PriceReviewTypeEnum.DETAIL:
-				return t -> PriceDetailTableColEnum.contain(t, PriceDetailTableColEnum.TypeEnum.PRICE);
-		}
-		return t -> false;
-	}
-	
-}
+//package com.gx.obe.step.price.utils;
+//
+//import java.util.ArrayList;
+//import java.util.List;
+//import java.util.function.Predicate;
+//import java.util.stream.Collectors;
+//import java.util.stream.Stream;
+//
+//import com.gx.obe.business.entity.EvaluationStepFactor;
+//import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+//import com.gx.obe.components.core.enumeration.PriceReviewTypeEnum;
+//import com.gx.obe.datastruct.tree.Forest;
+//import com.gx.obe.step.price.enums.PriceDetailTableColEnum;
+//import com.gx.obe.step.service.StepFactorService;
+//import com.gx.obe.util.utils.CollectionUtils;
+//import com.gx.obe.util.utils.PredicateUtils;
+//import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+//import com.gx.obe.web.entity.evaluation.EvaluationStep;
+//import com.gx.obe.web.entity.tender.TenderProjectEntity;
+//import com.gx.obe.web.service.evaluation.EvaluationFactorService;
+//import com.gx.obe.web.service.evaluation.EvaluationStepFactorService;
+//
+//public interface IPriceEvalStep {
+//	
+//	EvaluationStepFactorService evaluationStepFactorService = new EvaluationStepFactorService();
+//	EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
+//	
+//	boolean isAdd();
+//	
+//	/**
+//	 * @Description: 根据步骤绑定的指标过滤指标树
+//	 * @author chenxw
+//	 * @param factorForest
+//	 */
+//	default void filterForestByStepFactor(TenderProjectEntity tenderProject, EvaluationStep evaluationStep, Forest<EvaluationFactor> factorForest) {
+//		List<EvaluationStepFactor> evaluationStepFactorList = StepFactorService.getListByAuditType(tenderProject.getId(), EvaluationFactorEnum.AUDIT_PRICE);
+//		if (CollectionUtils.isNull(evaluationStepFactorList)) {
+//			return;
+//		}
+//		Stream<String> factorIdStream = evaluationStepFactorList.stream().map(EvaluationStepFactor::getFactorId);
+//		if (!this.isAdd()) {
+//			List<Object> factorIdLsitByStepId = evaluationStepFactorService.getFactorIdLsitByStepId(evaluationStep.getId());
+//			factorIdStream = factorIdStream.filter(t -> !factorIdLsitByStepId.contains(t));
+//		}
+//		List<String> factorIdList = factorIdStream.collect(Collectors.toList());
+//		factorForest.filterPath(t -> !factorIdList.contains(t.getId()));
+//	}
+//	
+//	static boolean isCreatePriceStep(TenderProjectEntity tenderProject, List<EvaluationStepFactor> evaluationStepFactorList, String priceReviewType) {
+//		List<EvaluationFactor> priceEvalFactorList = evaluationFactorService.getAllEvaluationFactorList(tenderProject.getId(), EvaluationFactorEnum.AUDIT_PRICE);
+//		if (CollectionUtils.isNull(priceEvalFactorList)) {
+//			return false;
+//		}
+//		List<EvaluationFactor> list = new ArrayList<>(priceEvalFactorList);
+//		Forest<EvaluationFactor> factorForest = new Forest<>(list);
+//		if (CollectionUtils.isNotNull(evaluationStepFactorList)) {
+//			List<String> factorIdList = evaluationStepFactorList.stream().map(EvaluationStepFactor::getFactorId).collect(Collectors.toList());
+//			factorForest.filterPath(t -> !factorIdList.contains(t.getId()));
+//		}
+//		IPriceEvalStep.filterForestByReviewType(factorForest, priceReviewType);
+//		return !list.isEmpty();
+//	}
+//	
+//	/**
+//	 * @Description: 根据价格步骤的评审类型过滤指标树
+//	 * @author chenxw
+//	 * @param factorForest
+//	 */
+//	static void filterForestByReviewType(Forest<EvaluationFactor> factorForest, String priceReviewType) {
+//		factorForest.filterPath(PredicateUtils.map(EvaluationFactor::getBidPriceCode, getBidPriceCodePredicate(priceReviewType)));
+//	}
+//
+//	static Predicate<String> getBidPriceCodePredicate(String priceReviewType) {
+//		switch (priceReviewType) {
+//			//case PriceReviewTypeEnum.PRICE:
+//			case "1":
+//				return t -> !PriceDetailTableColEnum.contain(t, PriceDetailTableColEnum.TypeEnum.PRICE);
+//			//case PriceReviewTypeEnum.DETAIL:
+//			case "0":
+//				return t -> PriceDetailTableColEnum.contain(t, PriceDetailTableColEnum.TypeEnum.PRICE);
+//		}
+//		return t -> false;
+//	}
+//	
+//}
diff --git a/com.gx.obe.struct/META-INF/MANIFEST.MF b/com.gx.obe.struct/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000000000000000000000000000000000..edad0c48f8b38ab6372b5138b310d466cbd423c8
--- /dev/null
+++ b/com.gx.obe.struct/META-INF/MANIFEST.MF
@@ -0,0 +1,42 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Struct
+Bundle-SymbolicName: com.gx.obe.struct
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: com.gx.obe.struct.Activator
+Bundle-Vendor: GX
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ com.gx.obe.lib;bundle-version="1.0.0",
+ com.gx.obe.utils;bundle-version="1.0.0",
+ com.gx.obe.components.core,
+ com.gx.obe.business;bundle-version="1.0.0",
+ org.eclipse.swt.core,
+ com.gx.obe.common.file;bundle-version="1.0.0",
+ com.gx.obe.bind,
+ com.gx.obe.common.icons,
+ com.gx.obe.component,
+ com.gx.obe.common.widget,
+ com.gx.obe.step,
+ com.gx.obe.action,
+ com.gx.obe.common
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Automatic-Module-Name: com.gx.obe.struct
+Bundle-ActivationPolicy: lazy
+Export-Package: com.gx.obe.struct,
+ com.gx.obe.struct.action,
+ com.gx.obe.struct.beans,
+ com.gx.obe.struct.composite,
+ com.gx.obe.struct.dialog,
+ com.gx.obe.struct.enums,
+ com.gx.obe.struct.handler,
+ com.gx.obe.struct.inters,
+ com.gx.obe.struct.listener,
+ com.gx.obe.struct.service,
+ com.gx.obe.struct.thread,
+ com.gx.obe.struct.tree,
+ com.gx.obe.struct.utils
+Import-Package: com.gx.obe.action.bean,
+ com.gx.obe.config,
+ com.gx.obe.config.utils,
+ com.gx.obe.message
diff --git a/com.gx.obe.struct/build.properties b/com.gx.obe.struct/build.properties
new file mode 100644
index 0000000000000000000000000000000000000000..066e8aef67f2c18671b759c6842f55482b5e69e0
--- /dev/null
+++ b/com.gx.obe.struct/build.properties
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               icons/
+javacDefaultEncoding.. = UTF-8
diff --git a/com.gx.obe.struct/icons/auxevaluation.png b/com.gx.obe.struct/icons/auxevaluation.png
new file mode 100644
index 0000000000000000000000000000000000000000..1e43fbea2a91d1a3326ae0f639e467bdff0e238b
Binary files /dev/null and b/com.gx.obe.struct/icons/auxevaluation.png differ
diff --git a/com.gx.obe.struct/icons/value.png b/com.gx.obe.struct/icons/value.png
new file mode 100644
index 0000000000000000000000000000000000000000..717a5b72dfff9223f7e9a93f2533ff91181ab5a3
Binary files /dev/null and b/com.gx.obe.struct/icons/value.png differ
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/Action.java b/com.gx.obe.struct/src/com/gx/obe/struct/Action.java
new file mode 100644
index 0000000000000000000000000000000000000000..11863c0403c26b820aed870376ea7af85427b5f7
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/Action.java
@@ -0,0 +1,186 @@
+package com.gx.obe.struct;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import com.gx.obe.util.utils.UuidUtils;
+import com.gx.obe.web.entity.auth.Menu;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.entity.tender.TenderProjectRuleEntity;
+import com.gx.obe.web.service.ProjectRuleService;
+import com.gx.obe.web.service.TenderProjectService;
+
+/**
+ * @Description:封装公共action接口 
+ * @author guoyr
+ */
+public abstract class Action {
+	private String id = UuidUtils.getUUID();
+	private ActionListener listener;
+	public abstract void run();
+	private Map<String, Object> data = null;
+	private TenderProjectEntity parentProject;
+	private TenderProjectEntity tenderProject;
+	private TenderProjectRuleEntity tenderProjectRule;
+	private TenderProjectService tenderProjectService;
+	private ProjectRuleService projectRuleService;
+	private EvaluationStep evaluationStep;
+	
+	private Menu menu;
+	
+	/**
+	 * @Description: 添加action监听
+	 * @author guoyr
+	 * @param listener
+	 */
+	public void addActionListener(ActionListener listener){
+		this.listener = listener;
+	}
+	
+
+	public TenderProjectEntity refreshParentProject() {
+		if(null == tenderProjectService){
+			tenderProjectService = new TenderProjectService();
+		}
+		parentProject = tenderProjectService.getById(parentProject.getId());
+		return parentProject;
+	}
+	
+	public TenderProjectEntity refreshTenderProject() {
+		if(null == tenderProjectService){
+			tenderProjectService = new TenderProjectService();
+		}
+		tenderProject = tenderProjectService.getById(tenderProject.getId());
+		tenderProject.setParentProjectEntity(parentProject);
+		return tenderProject;
+	}
+	
+
+	public TenderProjectRuleEntity refreshTenderProjectRule() {
+		if(null == projectRuleService){
+			projectRuleService = new ProjectRuleService();
+		}
+//		if(null != tenderProjectRule && null != tenderProjectRule.getId()){
+//		}
+		tenderProjectRule = projectRuleService.getProjectRule(tenderProject.getId());
+		if(null == tenderProjectRule) {
+			tenderProjectRule = new TenderProjectRuleEntity();
+			tenderProjectRule.setTenderId(tenderProject.getId());
+			tenderProjectRule.setId(UuidUtils.getUUID());
+			projectRuleService.insert(tenderProjectRule);
+		}
+		return tenderProjectRule;
+	}
+	
+
+	/**
+	 * @Description: 获取action监听
+	 * @author guoyr
+	 * @return
+	 */
+	public ActionListener getListener() {
+		return listener;
+	}
+
+	public Menu getMenu() {
+		return menu;
+	}
+
+	public void setMenu(Menu menu) {
+		this.menu = menu;
+	}
+
+	
+	public TenderProjectEntity getParentProject() {
+		return parentProject;
+	}
+
+	public void setParentProject(TenderProjectEntity parentProject) {
+		this.parentProject = parentProject;
+	}
+
+	public TenderProjectEntity getTenderProject() {
+		return tenderProject;
+	}
+
+	public void setTenderProject(TenderProjectEntity tenderProject) {
+		this.tenderProject = tenderProject;
+		this.tenderProject.setParentProjectEntity(getParentProject());
+	}
+
+	public TenderProjectRuleEntity getTenderProjectRule() {
+		return tenderProjectRule;
+	}
+
+	public void setTenderProjectRule(TenderProjectRuleEntity tenderProjectRule) {
+		this.tenderProjectRule = tenderProjectRule;
+	}
+
+	
+	public EvaluationStep getEvaluationStep() {
+		return evaluationStep;
+	}
+
+
+	public void setEvaluationStep(EvaluationStep evaluationStep) {
+		this.evaluationStep = evaluationStep;
+	}
+
+
+	/**
+	 * @Description: 设置data数据
+	 * @author guoyr
+	 * @param key
+	 * @param value
+	 */
+	public void setData(String key, Object value) {
+		if(data == null){
+			data = new HashMap<String, Object>();
+		}
+		data.put(key, value);
+	}
+
+	public Shell getParentShell(Shell parent){
+		if(null != parent && !parent.isDisposed()){
+			return parent;
+		}else {
+			Shell _parentShell = null;
+			_parentShell = Display.getDefault().getActiveShell();
+			if(null != _parentShell && !_parentShell.isDisposed()){
+				return _parentShell;
+			}else {
+				Shell[] shells = Display.getDefault().getShells();
+				if(null != shells && shells.length > 0){
+					for(int i = shells.length -1; i >= 0; i--){
+						if(null != shells[i] && !shells[i].isDisposed()){
+							return shells[i];
+						}
+					}
+				}
+			}
+		}
+		return new Shell(SWT.ON_TOP);
+	}
+	/**
+	 * @Description: 获取data数据
+	 * @author guoyr
+	 * @param key
+	 * @return
+	 */
+	public Object getData(String key) {
+		if(data != null){
+			return data.get(key);
+		}
+		return null;
+	}
+	@Override
+	public String toString() {
+		return id;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/ActionListener.java b/com.gx.obe.struct/src/com/gx/obe/struct/ActionListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..18e7a3437300055669801b39e95f470cf8d10c90
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/ActionListener.java
@@ -0,0 +1,32 @@
+package com.gx.obe.struct;
+
+import org.eclipse.swt.widgets.Composite;
+
+
+/**
+ * @Description: 公共的action监听接口
+ * @author guoyr
+ */
+public interface ActionListener{
+
+	/**
+	 * @Description: 重载监听
+	 * @author guoyr
+	 */
+	public void onLoad(Action action); 
+	
+	/**
+	 * @Description: 面板加载监听
+	 * @author guoyr
+	 * @param action
+	 * @param composite
+	 */
+	public void loadComposite(Action action, Composite composite);
+
+	/**
+	 * @Description: 获取父级面板
+	 * @author guoyr
+	 * @return
+	 */
+	public Composite getParentComposite();
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/Activator.java b/com.gx.obe.struct/src/com/gx/obe/struct/Activator.java
new file mode 100644
index 0000000000000000000000000000000000000000..92058afd25bf824b48a25924b35b88e5ad4a8765
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/Activator.java
@@ -0,0 +1,50 @@
+package com.gx.obe.struct;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+	// The plug-in ID
+	public static final String PLUGIN_ID = "com.gx.obe.struct"; //$NON-NLS-1$
+
+	// The shared instance
+	private static Activator plugin;
+	
+	/**
+	 * The constructor
+	 */
+	public Activator() {
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+	 */
+	public void start(BundleContext context) throws Exception {
+		super.start(context);
+		plugin = this;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+	 */
+	public void stop(BundleContext context) throws Exception {
+		plugin = null;
+		super.stop(context);
+	}
+
+	/**
+	 * Returns the shared instance
+	 *
+	 * @return the shared instance
+	 */
+	public static Activator getDefault() {
+		return plugin;
+	}
+
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/BidFileUtils.java b/com.gx.obe.struct/src/com/gx/obe/struct/BidFileUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..694ede16c2840acedc7156df197616f800b773b8
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/BidFileUtils.java
@@ -0,0 +1,24 @@
+package com.gx.obe.struct;
+
+import java.util.Optional;
+
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.util.utils.StringUtils;
+
+public class BidFileUtils {
+
+	/**
+	 * @Description: 获得投标文件文件名
+	 * @author chenxw
+	 * @param fileItem
+	 * @param isEnc
+	 * @return
+	 */
+	public static Optional<String> getBidFileName(String fileId, String fileName) {
+		Optional<String> suffix = Optional.ofNullable(fileId).map(FileUtils::removeFileNameENC).map(FileUtils::getFileNameBack).filter(t -> {
+			return !Constants.ZIP.equals(t);
+		});
+		return Optional.ofNullable(fileName).map(FileUtils::getFileNameFront).map(t -> t.concat(suffix.orElse(""))).filter(StringUtils::isNotEmpty);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/BusinessNowTimeUtils.java b/com.gx.obe.struct/src/com/gx/obe/struct/BusinessNowTimeUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..47f585a0360b0121bf05877d6084a2543b9a63e5
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/BusinessNowTimeUtils.java
@@ -0,0 +1,190 @@
+package com.gx.obe.struct;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.apache.log4j.Logger;
+
+import com.gx.obe.message.Messages;
+import com.gx.obe.web.service.ConnectionService;
+
+/**
+ * @Description: 获取当前时间
+ * @author guoyr
+ */
+public class BusinessNowTimeUtils {
+
+	private static long NOW_TIME = 0l;
+	private static Calendar GET_DATETIME_START_CALLENDAR;// 记录获取当前时间的时间点
+	private static final String weak[] = {Messages.Weak_sun, Messages.Weak_mon, Messages.Weak_tues, Messages.Weak_wed, Messages.Weak_thur, Messages.Weak_fri, Messages.Weak_sat};
+	private static final String weakDay[] = {Messages.Weak_sunday, Messages.Weak_monday, Messages.Weak_tuesday, Messages.Weak_wednesday, Messages.Weak_thursday, Messages.Weak_friday, Messages.Weak_saturday};
+//	private static final String weakEn[] = {"Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"};
+//	private static final String weakEnDay[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
+	private static Logger LOG = Logger.getLogger(BusinessNowTimeUtils.class);
+	public static String NOW_DATE_SOURCE = "本机时间";
+	private static boolean setTime = false;
+	private static ConnectionService connectionService = new ConnectionService();
+	
+	/**
+	 * @Description: 设置当前时间
+	 * @author guoyr
+	 * @param nowDate
+	 */
+	public static void setNowTime(Date nowDate){
+		Calendar cal = Calendar.getInstance();
+		
+		cal.setTime(nowDate);
+		NOW_TIME = cal.getTimeInMillis();
+		GET_DATETIME_START_CALLENDAR = Calendar.getInstance();
+		
+		// 标记为已设置当前时间
+		setTime = true;
+		
+		LOG.info("license设置当前时间为:" + nowDate);
+	}
+	
+	/**
+	 * @Description: 获取数据库或时间服务器中的当前时间 
+	 * @author guoyr
+	 * @return
+	 */
+	private static long getNowTime() {
+		// 如果还未设置当前时间
+		if(!setTime){
+			return new Date().getTime() ;
+		}
+		return NOW_TIME + (Calendar.getInstance().getTimeInMillis()-GET_DATETIME_START_CALLENDAR.getTimeInMillis());
+	}
+	
+	/**
+	 * @Description: 获得当前时间
+	 * @author guoyr
+	 * @return
+	 */
+	public static Date getNowDate(){
+		// 如果还未设置当前时间
+		if(!setTime){
+			return new Date();
+		}
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTimeInMillis(getNowTime());
+		return calendar.getTime();
+	}
+	
+	/**
+	 * @Description: 获得当前年份
+	 * @author guoyr
+	 * @return
+	 */
+	public static int getYear() {
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(getNowDate());
+		return calendar.get(Calendar.YEAR);
+	}
+	
+	/**
+	 * @Description: 获得当前星期
+	 * @author guoyr
+	 * @return
+	 */
+	public static String getWeak(){
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(getNowDate());
+		int dayOfWeak = calendar.get(Calendar.DAY_OF_WEEK)-1;
+		return weak[dayOfWeak];
+	}
+	/**
+	 * @Description: 获得当前星期
+	 * @author guoyr
+	 * @return
+	 */
+	public static String getWeakDay(){
+		Calendar calendar = Calendar.getInstance();
+		calendar.setTime(getNowDate());
+		int dayOfWeak = calendar.get(Calendar.DAY_OF_WEEK)-1;
+		return weakDay[dayOfWeak];
+	}
+	
+	
+	/**
+	 * @Description: 获得当前日期
+	 * @author guoyr
+	 * @return
+	 */
+	public static String getDate(){
+		return new SimpleDateFormat("yyyy-MM-dd").format(getNowDate());
+	}
+	
+	/**
+	 * @Description: 获得当前时间
+	 * @author guoyr
+	 * @return
+	 */
+	public static String getTime(){
+		return new SimpleDateFormat("HH:mm:ss").format(getNowDate());
+	}
+	
+	/**
+	 * @Description: 获得当前日期和时间
+	 * @author guoyr
+	 * @return
+	 */
+	public static String getDateTime(){
+		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(getNowDate());
+	}
+	
+	/**
+	 * @Description: 服务器的当前时间
+	 * @author guoyr
+	 * @return
+	 */
+	private static Date getServiceNowTime(){
+		Date nowDate = null;
+		long startTime = System.currentTimeMillis();    //获取开始时间
+		nowDate = connectionService.getServiceDate();
+		long endTime = System.currentTimeMillis();    //获取结束时间
+		if(null != nowDate){
+			long ms = endTime - startTime;
+			if(ms > 1000){
+				int second= (int) (ms / 1000);
+				Calendar calendar = Calendar.getInstance();
+				calendar.setTime(nowDate);
+				calendar.add(Calendar.SECOND, second);
+				nowDate = calendar.getTime();
+			}
+		}
+		return nowDate;
+	}
+	
+	/**
+	 * @Description: 获取时间服务器时间
+	 * @author guoyr
+	 * @return
+	 */
+//	private static Date getNowDateFormDateServer(){
+//		Date nowDate = null;
+//		try {
+//			String xmlStr = WebServiceUtil.invokeWebservice(PropertiesUtils.getWebserviceProperty(WebserviceConstants.WEBSERVICE_ADDRESS,"") + PropertiesUtils.getWebserviceProperty(WebserviceConstants.NOW_TIME_URL,""), PropertiesUtils.getWebserviceProperty(WebserviceConstants.NOW_TIME_METHOD,""), new Object[]{}, null);
+//			if(!"".equals(xmlStr)){
+//				Document document = DocumentHelper.parseText(xmlStr);
+//				Element root = document.getRootElement();
+//				String operTag = root.element("header").elementTextTrim("operTag");
+//				if(null != operTag && "Y".equals(operTag)){
+//					String timeStr = root.element("body").elementTextTrim("time");
+//					nowDate = DateUtils.toDate(timeStr);
+//					LOG.debug("获取时间服务器时间为" + nowDate);
+//				}else {
+//					LOG.error(root.element("header").elementTextTrim("operDesc"));
+//					LOG.error(root.element("header").elementTextTrim("operException"));
+//				}
+//			}else {
+//				LOG.error("获取时间服务器时间出错!");
+//			}
+//		} catch (Exception e) {
+//			LOG.error("", e);
+//			nowDate = null;
+//		}
+//		return nowDate;
+//	}
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/CAction.java b/com.gx.obe.struct/src/com/gx/obe/struct/CAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..19af586ccf2f6662fcd848cb8c8f37c3583f3b8a
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/CAction.java
@@ -0,0 +1,16 @@
+package com.gx.obe.struct;
+
+import org.eclipse.swt.widgets.Composite;
+
+public abstract class CAction extends Action {
+	
+	@Override
+	public void run() {
+		ActionListener listener = this.getListener();
+		listener.onLoad(this);
+		listener.loadComposite(this, initComposite(listener.getParentComposite()));
+	}
+	
+	protected abstract Composite initComposite(Composite parent);
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/ElementClass.java b/com.gx.obe.struct/src/com/gx/obe/struct/ElementClass.java
new file mode 100644
index 0000000000000000000000000000000000000000..95e0592a613af27ec5c7acb6c8ffcb7b3d1dbcae
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/ElementClass.java
@@ -0,0 +1,72 @@
+package com.gx.obe.struct;
+
+
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+public class ElementClass<T> {
+	
+	private Class<T> tClass;
+	
+	private List<FieldInfo> fieldInfoList;
+	
+	public static <T> ElementClass<T> of(Class<T> tClass) {
+		return new ElementClass<>(tClass);
+	}
+	
+	public ElementClass(Class<T> tClass) {
+		this.tClass = tClass;
+		this.fieldInfoList = Arrays.stream(tClass.getDeclaredFields()).map(this::createFieldInfo).filter(t -> t != null).collect(Collectors.toList());;
+	}
+	
+	private FieldInfo createFieldInfo(Field field) {
+		PropertyDescriptor descriptor = null;
+		try {
+			descriptor = new PropertyDescriptor(field.getName(), tClass);
+		} catch (IntrospectionException e) {
+			return null;
+		}
+		return new FieldInfo(field, descriptor.getWriteMethod());
+	}
+	
+	public T create(Element element) {
+		T t;
+		try {
+			t = tClass.newInstance();
+		} catch (InstantiationException | IllegalAccessException e) {
+			return null;
+		}
+		fieldInfoList.forEach(fieldInfo -> fieldInfo.mapValue(t, element));
+		return t;
+	}
+	
+	public List<T> createList(Element element) {
+		List<?> elements = element.elements();
+		return elements.stream().map(t -> create((Element) t)).collect(Collectors.toList());
+	}
+	
+	public T create(String xml) {
+		try {
+			return create(DocumentHelper.parseText(xml).getRootElement());
+		} catch (DocumentException e) {
+			throw new RuntimeException(e);
+		}
+	}
+	
+	public List<T> createList(String xml) {
+		try {
+			return createList(DocumentHelper.parseText(xml).getRootElement());
+		} catch (DocumentException e) {
+			throw new RuntimeException(e);
+		}
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/ElementUtils.java b/com.gx.obe.struct/src/com/gx/obe/struct/ElementUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..9dc94c00b6396a78584b7435c9d102efdd60a8d2
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/ElementUtils.java
@@ -0,0 +1,23 @@
+package com.gx.obe.struct;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.dom4j.Element;
+
+public class ElementUtils {
+	
+	public static Function<Element, Stream<Element>> toStreamFun(String listName, String itemName) {
+		return e -> {
+			List<?> elements = Optional.ofNullable(e).map(t -> t.element(listName)).map(t -> t.elements(itemName)).orElse(null);
+			if (elements == null) return null;
+			return elements.stream().map(t -> (Element) t);
+		};
+	}
+	
+	public static <T> Element as(T t) {
+	    return (Element) t;
+	  }
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/EvalFactorText.java b/com.gx.obe.struct/src/com/gx/obe/struct/EvalFactorText.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f1ab6c83eda37d4b882fe07191a7519260b16bd
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/EvalFactorText.java
@@ -0,0 +1,53 @@
+package com.gx.obe.struct;
+
+import java.text.NumberFormat;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.component.text.FStyledText;
+import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+import com.gx.obe.message.Messages;
+import com.gx.obe.util.utils.StringUtils;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.swtdesigner.SWTResourceManager;
+
+public class EvalFactorText extends FStyledText {
+	
+	protected EvaluationFactor curFactor;
+	
+	public EvalFactorText(Composite parent) {
+		super(parent);
+	}
+	
+	public void refresh(EvaluationFactor curFactor) {
+		this.curFactor = curFactor;
+		clear();
+		if (curFactor != null) initItem();
+		refresh();
+	}
+	
+	protected void initItem() {
+		addEvalFactor();
+		addScoreRange();
+		addEvalExplain();
+	}
+	
+	protected void addEvalFactor() {
+		add(Messages.EvalFactor + ":", curFactor.getFactorName(), SWTResourceManager.getColor(20, 20, 20), SWT.NORMAL);
+	}
+	
+	protected void addScoreRange() {
+		if (EvaluationFactorEnum.AUDIT_COMPLIANCE.equals(curFactor.getAuditType())) return;
+		String factorMinScore = NumberFormat.getInstance().format(curFactor.getFactorMinScore());
+		String factorMaxScore = NumberFormat.getInstance().format(curFactor.getFactorMaxScore());
+		add(Messages.ScoreRange + ":", "[" + factorMinScore + "-" + factorMaxScore + Messages.Points + "]", SWTResourceManager.getColor(77, 163, 19), SWT.BOLD);
+	}
+	
+	protected void addEvalExplain() {
+		if (StringUtils.isEmpty(curFactor.getMemo())) return;
+		addWrap(Messages.EvalExplain + ":", curFactor.getMemo(), SWTResourceManager.getColor(100, 100, 100), SWT.NORMAL);
+	}
+	
+}
+
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/ExcelReport.java b/com.gx.obe.struct/src/com/gx/obe/struct/ExcelReport.java
new file mode 100644
index 0000000000000000000000000000000000000000..28fcabe34ee132e31bdc31e8f247cdd32cf5f353
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/ExcelReport.java
@@ -0,0 +1,12 @@
+package com.gx.obe.struct;
+
+import java.util.Map;
+
+import com.gx.obe.bind.promise.Promise;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+
+public interface ExcelReport {
+	
+	Promise<String> generate(TenderProjectEntity tenderProject, String templatePath, String reportOutPath, Map<String, Object> dateMap);
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/FAction.java b/com.gx.obe.struct/src/com/gx/obe/struct/FAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..bbbfb60b8e16c265f18250e4b3f1f87b581ab916
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/FAction.java
@@ -0,0 +1,25 @@
+package com.gx.obe.struct;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.component.rx.RxSwt;
+
+public abstract class FAction<T> extends Action {
+	
+	@Override
+	public void run() {
+		ActionListener listener = this.getListener();
+		listener.onLoad(this);
+		RxSwt.run(this::supply).checkWidget(listener.getParentComposite()).exe(this::loadComposite);
+	}
+	
+	private void loadComposite(T t) {
+		ActionListener listener = this.getListener();
+		listener.loadComposite(this, consume(listener.getParentComposite(), t));
+	}
+	
+	protected abstract T supply();
+	
+	protected abstract Composite consume(Composite parent, T t);
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/FieldInfo.java b/com.gx.obe.struct/src/com/gx/obe/struct/FieldInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..f96a64f34e5f9a2f56bf122fe7a76476840f3e1b
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/FieldInfo.java
@@ -0,0 +1,66 @@
+package com.gx.obe.struct;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.dom4j.Element;
+
+
+
+public class FieldInfo {
+	
+	private String name;
+	
+	private Method writeMethod;
+	
+	private FieldType type;
+	
+	private Class<?> fClass;
+	
+	public FieldInfo(Field field, Method writeMethod) {
+		this.name = field.getName();
+		this.writeMethod = writeMethod;
+		this.fClass = field.getType();
+		if (fClass == String.class) this.type = FieldType.STRING;
+		else if (fClass == List.class) {
+			ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
+			this.fClass = (Class<?>) parameterizedType.getActualTypeArguments()[0];
+			this.type = fClass == String.class ? FieldType.LIST_STRING : FieldType.LIST_OBJECT;
+		} else this.type = FieldType.OBJECT;
+	}
+	
+	public void mapValue(Object obj, Element element) {
+		Object value = getValue(element);
+		if (value == null) return;
+		try {
+			writeMethod.invoke(obj, value);
+		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {}
+	}
+	
+	private Object getValue(Element element) {
+		Element fieldElement = element.element(name);
+		if (fieldElement == null) return null;
+		List<?> elements = fieldElement.elements();
+		switch (type) {
+			case STRING:
+				return fieldElement.getTextTrim();
+			case OBJECT:
+				return ElementClass.of(fClass).create(fieldElement);
+			case LIST_STRING:
+				return elements.stream().map(ElementUtils::as).map(Element::getTextTrim).collect(Collectors.toList());
+			case LIST_OBJECT:
+				return elements.stream().map(ElementUtils::as).map(ElementClass.of(fClass)::create).collect(Collectors.toList());
+			default:
+				return null;
+		}
+	}
+	
+	public enum FieldType {
+		STRING, OBJECT, LIST_STRING, LIST_OBJECT;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/FileUtils.java b/com.gx.obe.struct/src/com/gx/obe/struct/FileUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3e92036b9c09161bec5e46cae4a0ca8b646cb06
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/FileUtils.java
@@ -0,0 +1,74 @@
+package com.gx.obe.struct;
+
+import java.util.function.Function;
+
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.util.utils.StringUtils;
+
+public class FileUtils {
+
+	/**
+	 * @Description: 去除文件名.enc后缀
+	 * @author chenxw
+	 * @param fileName
+	 * @return
+	 */
+	public static String removeFileNameENC(String fileName) {
+		if (StringUtils.isEmpty(fileName)) {
+			return fileName;
+		}
+		if (fileName.endsWith(Constants.ENC)) {
+			return fileName.substring(0, fileName.lastIndexOf(Constants.ENC));
+		}
+		return fileName;
+	}
+	
+	/**
+	 * @Description: 获取文件名前部
+	 * @author chenxw
+	 * @param fileName
+	 * @return
+	 */
+	public static String getFileNameFront(String fileName) {
+		if (StringUtils.isEmpty(fileName)) {
+			return fileName;
+		}
+		int lastIndex = fileName.lastIndexOf(".");
+		if (lastIndex == -1) {
+			return fileName;
+		}
+		return fileName.substring(0, lastIndex);
+	}
+	
+	/**
+	 * @Description: 获取文件名后部
+	 * @author chenxw
+	 * @param fileName
+	 * @return
+	 */
+	public static String getFileNameBack(String fileName) {
+		if (StringUtils.isEmpty(fileName)) {
+			return fileName;
+		}
+		int lastIndex = fileName.lastIndexOf(".");
+		if (lastIndex == -1) {
+			return "";
+		}
+		return fileName.substring(lastIndex);
+	}
+	
+	public static Function<String, String> funGetSuffix = fileName -> {
+		if (fileName == null) return "";
+		int indexOf = fileName.lastIndexOf(".");
+		if (indexOf == -1) return "";
+		return fileName.substring(indexOf + 1);
+	};
+	
+	public static Function<String, String> funRemSuffix = fileName -> {
+		if (fileName == null) return "";
+		int indexOf = fileName.lastIndexOf(".");
+		if (indexOf == -1) return fileName;
+		return fileName.substring(0, indexOf);
+	};
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/Global.java b/com.gx.obe.struct/src/com/gx/obe/struct/Global.java
new file mode 100644
index 0000000000000000000000000000000000000000..65e8109266433f5d7fdc4cd97d56da70f26b03ab
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/Global.java
@@ -0,0 +1,27 @@
+package com.gx.obe.struct;
+
+import org.eclipse.swt.widgets.Composite;
+
+public class Global {
+	
+	/**
+	 * @Description: Excel报表
+	 */
+	public static ExcelReport EXCEL_REPORT;
+	
+	/**
+	 * @Description: pdf文件显示器
+	 */
+	public static LoadPdfFileView PDF_FILE_VIEW = (Composite parent, int style) -> new PdfFileView() {
+		public void setFileNotExistMessage(String fileNotExistMessage) {}
+		
+		public void setCacheNumber(int cacheNumber) {}
+		
+		public void releaseFile(String filePath) {}
+		
+		public void openFile(String filePath, int page) {}
+		
+		public void openFile(String filePath) {}
+	};
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/LoadPdfFileView.java b/com.gx.obe.struct/src/com/gx/obe/struct/LoadPdfFileView.java
new file mode 100644
index 0000000000000000000000000000000000000000..f9acf3456cbdfcf5a0c76824335faae6858da191
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/LoadPdfFileView.java
@@ -0,0 +1,9 @@
+package com.gx.obe.struct;
+
+import org.eclipse.swt.widgets.Composite;
+
+public interface LoadPdfFileView {
+	
+	PdfFileView load(Composite parent, int style);
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/PdfFileView.java b/com.gx.obe.struct/src/com/gx/obe/struct/PdfFileView.java
new file mode 100644
index 0000000000000000000000000000000000000000..1eda9c9b11771d42e2612e2ece9ed44f60cd188d
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/PdfFileView.java
@@ -0,0 +1,15 @@
+package com.gx.obe.struct;
+
+public interface PdfFileView {
+	
+	void setFileNotExistMessage(String fileNotExistMessage);
+	
+	void setCacheNumber(int cacheNumber);
+	
+	void openFile(String filePath);
+	
+	void openFile(String filePath, int page);
+
+	void releaseFile(String filePath);
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/ProgressMessageTangent.java b/com.gx.obe.struct/src/com/gx/obe/struct/ProgressMessageTangent.java
new file mode 100644
index 0000000000000000000000000000000000000000..13e38502c70cde0260f94bbf24b626c68eb9fcc1
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/ProgressMessageTangent.java
@@ -0,0 +1,34 @@
+package com.gx.obe.struct;
+
+
+import org.eclipse.swt.widgets.Shell;
+
+import com.gx.obe.bind.rx.Tangent;
+import com.gx.obe.common.widget.shell.ProgressMessageDialog;
+
+public class ProgressMessageTangent implements Tangent {
+	
+	private ProgressMessageDialog dialog;
+	
+	public ProgressMessageTangent(Shell parentShell, String title) {
+		this.dialog = new ProgressMessageDialog(parentShell, false, -1, null);
+		this.dialog.setTitle(title);
+	}
+	
+	@Override
+	public void before() {
+		dialog.open();
+	}
+	
+	@Override
+	public void after() {
+		dialog.finish(dialog.getErrorMessagesSize() == 0);
+	}
+	
+	@Override
+	public void error(Exception e) {
+		dialog.message(e.getMessage(), -1);
+		dialog.finish(false);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/StructBusinessTypeEnum.java b/com.gx.obe.struct/src/com/gx/obe/struct/StructBusinessTypeEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d37773ca119b0dec180be014df7c2ee09c45059
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/StructBusinessTypeEnum.java
@@ -0,0 +1,225 @@
+package com.gx.obe.struct;
+
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import com.gx.obe.util.utils.PredicateUtil;
+
+/**
+ * @Description: 结构化商务类型
+ * @author chenxw
+ */
+public enum StructBusinessTypeEnum {
+	
+//	ENTERPRISE_QUALIFICATION("EnterpriseQualification", "企业资质证明文件"),
+	
+//	EQ_ENTERPRISE_INFO("EQ_EnterpriseInfo", ""),
+	
+	/**
+	 * null
+	 */
+	NULL("null", ""),
+	
+	/**
+	 * 营业执照 EQ_BusinessLicense
+	 */
+	EQ_BUSINESS_LICENSE("EQ_BusinessLicense", "营业执照"),
+	
+	/**
+	 * 供货业绩(物资) EQ_Achievements
+	 */
+	EQ_ACHIEVEMENTS("EQ_Achievements", "供货业绩(物资)"),
+	
+	/**
+	 * 已投产业绩 EQ_OperationAchievements
+	 */
+	EQ_OPERATION_ACHIEVEMENTS("EQ_OperationAchievements", "已投产业绩"),
+	
+	/**
+	 * 在建业绩(施工/服务) EQ_OperationPerformance
+	 */
+	EQ_OPERATION_PERFORMANCE("EQ_OperationPerformance", "在建业绩(施工/服务)"),
+	
+	/**
+	 * 合同业绩  EQ_ContractPerformance
+	 */
+	EQ_CONTRACT_PERFORMANCE("EQ_ContractPerformance", "合同业绩"),
+	
+	/**
+	 * 项目负责人  EQ_ProjectLeader
+	 */
+	EQ_PROJECTLEADER("EQ_ProjectLeader", "项目负责人"),
+	
+	/**
+	 * 资产负债率 EQ_AssetLiabilityRatio
+	 */
+	EQ_ASSETLIABILITY_RATIO("EQ_AssetLiabilityRatio", "资产负债率"),
+	
+	/**
+	 * 流动比率 EQ_LiquidityRatio
+	 */
+	EQ_LIQUIDITY_RATIO("EQ_LiquidityRatio", "流动比率"),
+	
+	/**
+	 * 主营业务利润率 EQ_ProfitRatio
+	 */
+	EQ_PROFIT_RATIO("EQ_ProfitRatio", "主营业务利润率"),
+
+	/**
+	 * 安全生产许可证  EQ_Qualification_SCXK
+	 */
+	EQ_QUALIFICATION_SCXK("EQ_Qualification_SCXK", "安全生产许可证"),
+	
+	/**
+	 * 检验报告  EQ_Qualification_SurveyReport
+	 */
+	EQ_QUALIFICATION_SURVEYREPORT("EQ_Qualification_SurveyReport", "检验报告"),
+	
+	/**
+	 *  资信等级 EQ_Qualification_ZXDJ
+	 */
+	EQ_QUALIFICATION_ZXDJ("EQ_Qualification_ZXDJ", "资信等级"),
+	
+	/**
+	 * 施工资质  EQ_Qualification_SGZZ
+	 */
+	EQ_QUALIFICATION_SGZZ("EQ_Qualification_SGZZ", "施工资质"),
+	
+	/**
+	 * 设计资质  EQ_Qualification_SJZZ
+	 */
+	EQ_QUALIFICATION_SJZZ("EQ_Qualification_SJZZ", "设计资质"),
+	
+	/**
+	 * 监理资质  EQ_Qualification_JLZZ
+	 */
+	EQ_QUALIFICATION_JLZZ("EQ_Qualification_JLZZ", "监理资质"),
+	
+	/**
+	 * 其它资质 EQ_Qualification
+	 */
+	EQ_QUALIFICATION("EQ_Qualification", "其它资质"),
+
+//	EQ_QUALIFICATION_ZLJX("EQ_Qualification_ZLJX", "质量奖项"),
+	
+//	EQ_QUALIFICATION_ZLJX_SJ("EQ_Qualification_ZLJX_SJ", "自治区质量奖项"),
+	
+//	EQ_QUALIFICATION_KJYF("EQ_Qualification_KJYF", "科技研发奖项"),
+	
+//	EQ_QUALIFICATION_KJYF_SJ("EQ_Qualification_KJYF_SJ", "自治区科技奖项"),
+	
+//	EQ_QUALIFICATION_HYPM("EQ_Qualification_HYPM", "行业排名"),
+	
+//	EQ_QUALIFICATION_XJS("EQ_Qualification_XJS", "新技术"),
+	
+//	EQ_QUALIFICATION_CPRZ("EQ_Qualification_CPRZ", "产品认证证书"),
+	
+//	EQ_QUALIFICATION_HBTX("EQ_Qualification_HBTX", "环保体系认证证书"),
+	
+	/**
+	 * 投标函   TenderLetter
+	 */
+	TENDER_LETTER("TenderLetter", "投标函"),
+
+	/**
+	 * 法定代表人身份证明  LegalRepresentativeIdCertificate
+	 */
+	LEGAL_REPRESENTATIVE_ID_CERTIFICATE("LegalRepresentativeIdCertificate", "法定代表人身份证明"),
+
+	/**
+	 * 法定代表人授权书  LegalRepresentative
+	 */
+	LEGAL_REPRESENTATIVE("LegalRepresentative", "法定代表人授权书"),
+
+	/**
+	 * 联合体协议书  ConsortiumAgreement
+	 */
+	CONSORTIUM_AGREEMENT("ConsortiumAgreement", "联合体协议书"),
+	
+	/**
+	 * 投标人关于资格的声明函   BidderQualificationStatement
+	 */
+	BIDDER_QUALIFICATION_STATEMENT("BidderQualificationStatement", "投标人关于资格的声明函"),
+	
+	/**
+	 * 不存在禁止投标的情形   BidProhibitionSituation
+	 */
+	BID_PROHIBITION_SITUATION("BidProhibitionSituation", "不存在禁止投标的情形"),
+
+	/**
+	 * 投标保证金 BidBond
+	 */
+	BID_BOND("BidBond", "投标保证金"),
+	
+	/**
+	 * 投标人名称 BidderName
+	 */
+	BIDDER_NAME("BidderName", "投标人名称"),
+	
+	/**
+	 * 工期 Duration
+	 */
+	DURATION("Duration", "工期");
+	
+//	/**
+//	 * 发包人要求  ContractorConditions
+//	 */
+//	CONTRACTOR_CONDITIONS("ContractorConditions", "发包人要求");
+//	
+//	/**
+//	 * 质量标准 QualityStandard
+//	 */
+//	QUALITY_STANDARD("QualityStandard", "质量标准"),
+//
+//	/**
+//	 * 权利与义务 RightAndDuty
+//	 */
+//	RIGHT_AND_DUTY("RightAndDuty", "权利与义务"),
+//
+//	/**
+//	 * 分包资格评审   PackQualification
+//	 */
+//	PACK_QUALIFICATION("PackQualification", "分包资格评审");
+
+	private final String key;
+	private final String value;
+	
+	private StructBusinessTypeEnum(String key, String value) {
+		this.key = key;
+		this.value = value;
+	}
+	
+	public String getKey() {
+		return key;
+	}
+	
+	public String getValue() {
+		return value;
+	}
+	
+	/**
+	 * @Description: 
+	 * @author chenxw
+	 * @param object
+	 * @return 
+	 */
+	public static Optional<StructBusinessTypeEnum> getBykey(String key) {
+		return Arrays.stream(values()).filter(PredicateUtil.get(StructBusinessTypeEnum::getKey, Predicate.isEqual(key))).findAny();
+	}
+
+	private static Set<String> keySet = Arrays.stream(values()).map(StructBusinessTypeEnum::getKey).filter(Predicate.isEqual(NULL.getKey()).negate()).collect(Collectors.toSet());
+	
+	/**
+	 * @Description: 
+	 * @author chenxw
+	 * @param key
+	 * @return 
+	 */
+	public static boolean contains(String key) {
+		return keySet.contains(key);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/action/FactorClearBidEvaluationAction.java b/com.gx.obe.struct/src/com/gx/obe/struct/action/FactorClearBidEvaluationAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..50ff2e092f27fdeb724299cc1521514c75f81929
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/action/FactorClearBidEvaluationAction.java
@@ -0,0 +1,19 @@
+package com.gx.obe.struct.action;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.step.listener.ExpertEvaluationListener;
+import com.gx.obe.struct.CAction;
+import com.gx.obe.struct.composite.FactorClearBidEvaluationComposite;
+
+public class FactorClearBidEvaluationAction extends CAction {
+	
+	@Override
+	protected Composite initComposite(Composite parent) {
+		FactorClearBidEvaluationComposite composite = new FactorClearBidEvaluationComposite(parent, getTenderProject(), getEvaluationStep());
+		composite.addExpertEvaluationListener((ExpertEvaluationListener) this.getData("expertEvaluationListener"));
+		composite.hideLeft(this.getData("hideLeft") != null);
+		return composite;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/action/FactorClearBidEvaluationResultAction.java b/com.gx.obe.struct/src/com/gx/obe/struct/action/FactorClearBidEvaluationResultAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..8524cb5d35277d38699a8f1218cc68d73c07f103
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/action/FactorClearBidEvaluationResultAction.java
@@ -0,0 +1,28 @@
+package com.gx.obe.struct.action;
+
+import java.util.List;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.struct.FAction;
+import com.gx.obe.struct.composite.FactorClearBidEvaluationResultComposite;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.web.entity.expert.Expert;
+import com.gx.obe.web.service.expert.ExpertService;
+
+public class FactorClearBidEvaluationResultAction extends FAction<String> {
+	
+	private final ExpertService expertService = new ExpertService();
+	
+	@Override
+	protected String supply() {
+		List<Expert> experts = expertService.getEvaluationStepExpertList(getTenderProject().getId(), getEvaluationStep());
+		return CollectionUtils.isNotNull(experts) ? experts.get(0).getUserId() : null;
+	}
+	
+	@Override
+	protected Composite consume(Composite parent, String userId) {
+		return new FactorClearBidEvaluationResultComposite(parent, getTenderProject(), getEvaluationStep(), userId);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/AbsoluteDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/AbsoluteDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..b7ef4cb901328833ba314cd624e7b01cfa792666
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/AbsoluteDO.java
@@ -0,0 +1,49 @@
+package com.gx.obe.struct.beans;
+
+import java.math.BigDecimal;
+
+/**
+ * @author gnauh
+ * 数值区间模型类
+ *
+ */
+public class AbsoluteDO {
+	private int startNumber;
+	private int endNumber;
+	private BigDecimal score;
+	public AbsoluteDO(int startNumber,int  endNumber , BigDecimal score){
+		this.score = score;
+		this.endNumber = endNumber;
+		this.startNumber = startNumber;
+	}
+	public int getStartNumber() {
+		return startNumber;
+	}
+	public void setStartNumber(int startNumber) {
+		this.startNumber = startNumber;
+	}
+	public int getEndNumber() {
+		return endNumber;
+	}
+	public void setEndNumber(int endNumber) {
+		this.endNumber = endNumber;
+	}
+	public BigDecimal getScore() {
+		return score;
+	}
+	public void setScore(BigDecimal score) {
+		this.score = score;
+	}
+	public boolean isInRange(int value) {
+		if (startNumber > 0 && endNumber> 0) {
+			 return value >= startNumber && value < endNumber;
+		}else if(startNumber > 0 &&  endNumber <=0) {
+			 return value >= startNumber;
+		}else if(startNumber ==0 && endNumber> 0) {
+			 return  value < endNumber;
+		}
+		return false;
+		
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/AbsoluteModelDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/AbsoluteModelDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..fdc543eda87e8fe1dbf072b06f2442b9703d1f92
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/AbsoluteModelDO.java
@@ -0,0 +1,43 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * 绝对值模型参数初始值模型
+ * @author gnauh
+ *
+ */
+public class AbsoluteModelDO {
+//	<!--起始整数绝对值-->
+	private String initialValue;
+//	 <!--整数绝对值单位-->
+	private String absoluteUnit;
+//	  <!--整数绝对值对应分值-->
+	private String absoluteScore;
+//	  <!--最高得分-->
+	private String maxScore;
+	
+	public String getMaxScore() {
+		return maxScore;
+	}
+	public void setMaxScore(String maxScore) {
+		this.maxScore = maxScore;
+	}
+	public String getInitialValue() {
+		return initialValue;
+	}
+	public void setInitialValue(String initialValue) {
+		this.initialValue = initialValue;
+	}
+	public String getAbsoluteUnit() {
+		return absoluteUnit;
+	}
+	public void setAbsoluteUnit(String absoluteUnit) {
+		this.absoluteUnit = absoluteUnit;
+	}
+	public String getAbsoluteScore() {
+		return absoluteScore;
+	}
+	public void setAbsoluteScore(String absoluteScore) {
+		this.absoluteScore = absoluteScore;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/AttachmentFile.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/AttachmentFile.java
new file mode 100644
index 0000000000000000000000000000000000000000..aeefcce6ec03fff403282c2c307ef483e20bcb39
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/AttachmentFile.java
@@ -0,0 +1,120 @@
+package com.gx.obe.struct.beans;
+
+import java.util.Date;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class AttachmentFile {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 父级ID
+	 */
+	private String parentId;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 业务ID
+	 */
+	private String businessId;
+	/**
+	 * 文件地址
+	 */
+	private String fileUrl;
+	/**
+	 * 文件名称
+	 */
+	private String fileName;
+	/**
+	 * 文件大小
+	 */
+	private Integer fileSize;
+	/**
+	 * 文件类型
+	 */
+	private String fileType;
+	/**
+	 * 创建时间
+	 */
+	private Date createTime;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getParentId() {
+		return parentId;
+	}
+	
+	public void setParentId(String parentId) {
+		this.parentId = parentId;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getBusinessId() {
+		return businessId;
+	}
+	
+	public void setBusinessId(String businessId) {
+		this.businessId = businessId;
+	}
+	
+	public String getFileUrl() {
+		return fileUrl;
+	}
+	
+	public void setFileUrl(String fileUrl) {
+		this.fileUrl = fileUrl;
+	}
+	
+	public String getFileName() {
+		return fileName;
+	}
+	
+	public void setFileName(String fileName) {
+		this.fileName = fileName;
+	}
+	
+	public Integer getFileSize() {
+		return fileSize;
+	}
+	
+	public void setFileSize(Integer fileSize) {
+		this.fileSize = fileSize;
+	}
+	
+	public String getFileType() {
+		return fileType;
+	}
+	
+	public void setFileType(String fileType) {
+		this.fileType = fileType;
+	}
+	
+	public Date getCreateTime() {
+		return createTime;
+	}
+	
+	public void setCreateTime(Date createTime) {
+		this.createTime = createTime;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/BalanceSheet.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/BalanceSheet.java
new file mode 100644
index 0000000000000000000000000000000000000000..3fd3a900e76b5cedb965012fb93a44d8ab5dd10b
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/BalanceSheet.java
@@ -0,0 +1,156 @@
+package com.gx.obe.struct.beans;
+
+import java.math.BigDecimal;
+
+/**
+ * @Description: 资产负债表
+ * @author chenxw
+ */
+public class BalanceSheet {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 财务ID
+	 */
+	private String financeId;
+	/**
+	 * 总资产
+	 */
+	private BigDecimal balanceTotal;
+	/**
+	 * 流动资产
+	 */
+	private BigDecimal balanceCecurrentAssets;
+	/**
+	 * 存货
+	 */
+	private BigDecimal inventory;
+	/**
+	 * 应收账款
+	 */
+	private BigDecimal receivables;
+	/**
+	 * 不良资产
+	 */
+	private BigDecimal badAssets;
+	/**
+	 * 总负债
+	 */
+	private BigDecimal balanceTotalliabilities;
+	/**
+	 * 流动负债
+	 */
+	private BigDecimal balanceCurrentLiabilities;
+	/**
+	 * 所有者权益
+	 */
+	private BigDecimal ownershipInterest;
+	/**
+	 * 其中:当年非正常增加
+	 */
+	private BigDecimal abnormalIncrease;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getFinanceId() {
+		return financeId;
+	}
+	
+	public void setFinanceId(String financeId) {
+		this.financeId = financeId;
+	}
+	
+	public BigDecimal getBalanceTotal() {
+		return balanceTotal;
+	}
+	
+	public void setBalanceTotal(BigDecimal balanceTotal) {
+		this.balanceTotal = balanceTotal;
+	}
+	
+	public BigDecimal getBalanceCecurrentAssets() {
+		return balanceCecurrentAssets;
+	}
+	
+	public void setBalanceCecurrentAssets(BigDecimal balanceCecurrentAssets) {
+		this.balanceCecurrentAssets = balanceCecurrentAssets;
+	}
+	
+	public BigDecimal getInventory() {
+		return inventory;
+	}
+	
+	public void setInventory(BigDecimal inventory) {
+		this.inventory = inventory;
+	}
+	
+	public BigDecimal getReceivables() {
+		return receivables;
+	}
+	
+	public void setReceivables(BigDecimal receivables) {
+		this.receivables = receivables;
+	}
+	
+	public BigDecimal getBadAssets() {
+		return badAssets;
+	}
+	
+	public void setBadAssets(BigDecimal badAssets) {
+		this.badAssets = badAssets;
+	}
+	
+	public BigDecimal getBalanceTotalliabilities() {
+		return balanceTotalliabilities;
+	}
+	
+	public void setBalanceTotalliabilities(BigDecimal balanceTotalliabilities) {
+		this.balanceTotalliabilities = balanceTotalliabilities;
+	}
+	
+	public BigDecimal getBalanceCurrentLiabilities() {
+		return balanceCurrentLiabilities;
+	}
+	
+	public void setBalanceCurrentLiabilities(BigDecimal balanceCurrentLiabilities) {
+		this.balanceCurrentLiabilities = balanceCurrentLiabilities;
+	}
+	
+	public BigDecimal getOwnershipInterest() {
+		return ownershipInterest;
+	}
+	
+	public void setOwnershipInterest(BigDecimal ownershipInterest) {
+		this.ownershipInterest = ownershipInterest;
+	}
+	
+	public BigDecimal getAbnormalIncrease() {
+		return abnormalIncrease;
+	}
+	
+	public void setAbnormalIncrease(BigDecimal abnormalIncrease) {
+		this.abnormalIncrease = abnormalIncrease;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/BidderBasicInfo.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/BidderBasicInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..7777e92a544166830314d31cd7f94947a2cf1e09
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/BidderBasicInfo.java
@@ -0,0 +1,442 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class BidderBasicInfo {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 模型数据ID
+	 */
+	private String modelDataId;
+	/**
+	 * 投标人名称
+	 */
+	private String companyName;
+	/**
+	 * 注册地址
+	 */
+	private String registerLocation;
+	/**
+	 * 邮政编码
+	 */
+	private String postalCode;
+	/**
+	 * 联系人
+	 */
+	private String linkMan;
+	/**
+	 * 电话
+	 */
+	private String linkManPhone;
+	/**
+	 * 传真
+	 */
+	private String linkManFax;
+	/**
+	 * 网址
+	 */
+	private String linkManWebsite;
+	/**
+	 * 组织结构
+	 */
+	private String orgStructure;
+	/**
+	 * 法定代表人姓名
+	 */
+	private String legalRepresentativeName;
+	/**
+	 * 法定代表人技术职称
+	 */
+	private String legalRepresentativeTitle;
+	/**
+	 * 法定代表人电话
+	 */
+	private String legalRepresentativePhone;
+	/**
+	 * 技术负责人姓名
+	 */
+	private String technicalDirectorName;
+	/**
+	 * 技术负责人职称
+	 */
+	private String technicalDirectorTitle;
+	/**
+	 * 技术负责人电话
+	 */
+	private String technicalDirectorPhone;
+	/**
+	 * 成立时间
+	 */
+	private String setupTime;
+	/**
+	 * 企业资质等级
+	 */
+	private String companyQualificationLevel;
+	/**
+	 * 注册资金
+	 */
+	private String registeredCapital;
+	/**
+	 * 开户银行
+	 */
+	private String depositBank;
+	/**
+	 * 营业执照号
+	 */
+	private String bussinessLicense;
+	/**
+	 * 银行账号
+	 */
+	private String bankAccount;
+	/**
+	 * 员工总人数
+	 */
+	private String employeeNumber;
+	/**
+	 * 项目经理数量
+	 */
+	private String purchaserNumber;
+	/**
+	 * 高级职称人员数量
+	 */
+	private String seniorProfessionalPostNumber;
+	/**
+	 * 中极职称人员数量
+	 */
+	private String mediumProfessionalPostNumber;
+	/**
+	 * 初级职称人员数量
+	 */
+	private String primaryProfessionalPostNumber;
+	/**
+	 * 技工数量
+	 */
+	private String artisanNumber;
+	/**
+	 * 经营范围
+	 */
+	private String businessScope;
+	/**
+	 * 企业性质
+	 */
+	private String enterpriseNature;
+	/**
+	 * 股权结构
+	 */
+	private String equityStructure;
+	/**
+	 * 关联企业情况
+	 */
+	private String relatedCompanyInfo;
+	/**
+	 * 服务能力
+	 */
+	private String serviceAbility;
+	/**
+	 * 拟投入本项目设备
+	 */
+	private String preInputDevice;
+	/**
+	 * 备注
+	 */
+	private String memo;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getModelDataId() {
+		return modelDataId;
+	}
+	
+	public void setModelDataId(String modelDataId) {
+		this.modelDataId = modelDataId;
+	}
+	
+	public String getRegisterLocation() {
+		return registerLocation;
+	}
+	
+	public void setRegisterLocation(String registerLocation) {
+		this.registerLocation = registerLocation;
+	}
+	
+	public String getPostalCode() {
+		return postalCode;
+	}
+	
+	public void setPostalCode(String postalCode) {
+		this.postalCode = postalCode;
+	}
+	
+	public String getLinkMan() {
+		return linkMan;
+	}
+	
+	public void setLinkMan(String linkMan) {
+		this.linkMan = linkMan;
+	}
+	
+	public String getLinkManPhone() {
+		return linkManPhone;
+	}
+	
+	public void setLinkManPhone(String linkManPhone) {
+		this.linkManPhone = linkManPhone;
+	}
+	
+	public String getLinkManFax() {
+		return linkManFax;
+	}
+	
+	public void setLinkManFax(String linkManFax) {
+		this.linkManFax = linkManFax;
+	}
+	
+	public String getLinkManWebsite() {
+		return linkManWebsite;
+	}
+	
+	public void setLinkManWebsite(String linkManWebsite) {
+		this.linkManWebsite = linkManWebsite;
+	}
+	
+	public String getOrgStructure() {
+		return orgStructure;
+	}
+	
+	public void setOrgStructure(String orgStructure) {
+		this.orgStructure = orgStructure;
+	}
+	
+	public String getLegalRepresentativeName() {
+		return legalRepresentativeName;
+	}
+	
+	public void setLegalRepresentativeName(String legalRepresentativeName) {
+		this.legalRepresentativeName = legalRepresentativeName;
+	}
+	
+	public String getLegalRepresentativeTitle() {
+		return legalRepresentativeTitle;
+	}
+	
+	public void setLegalRepresentativeTitle(String legalRepresentativeTitle) {
+		this.legalRepresentativeTitle = legalRepresentativeTitle;
+	}
+	
+	public String getLegalRepresentativePhone() {
+		return legalRepresentativePhone;
+	}
+	
+	public void setLegalRepresentativePhone(String legalRepresentativePhone) {
+		this.legalRepresentativePhone = legalRepresentativePhone;
+	}
+	
+	public String getTechnicalDirectorName() {
+		return technicalDirectorName;
+	}
+	
+	public void setTechnicalDirectorName(String technicalDirectorName) {
+		this.technicalDirectorName = technicalDirectorName;
+	}
+	
+	public String getTechnicalDirectorTitle() {
+		return technicalDirectorTitle;
+	}
+	
+	public void setTechnicalDirectorTitle(String technicalDirectorTitle) {
+		this.technicalDirectorTitle = technicalDirectorTitle;
+	}
+	
+	public String getTechnicalDirectorPhone() {
+		return technicalDirectorPhone;
+	}
+	
+	public void setTechnicalDirectorPhone(String technicalDirectorPhone) {
+		this.technicalDirectorPhone = technicalDirectorPhone;
+	}
+	
+	public String getSetupTime() {
+		return setupTime;
+	}
+	
+	public void setSetupTime(String setupTime) {
+		this.setupTime = setupTime;
+	}
+	
+	public String getCompanyQualificationLevel() {
+		return companyQualificationLevel;
+	}
+	
+	public void setCompanyQualificationLevel(String companyQualificationLevel) {
+		this.companyQualificationLevel = companyQualificationLevel;
+	}
+	
+	public String getRegisteredCapital() {
+		return registeredCapital;
+	}
+	
+	public void setRegisteredCapital(String registeredCapital) {
+		this.registeredCapital = registeredCapital;
+	}
+	
+	public String getDepositBank() {
+		return depositBank;
+	}
+	
+	public void setDepositBank(String depositBank) {
+		this.depositBank = depositBank;
+	}
+	
+	public String getBussinessLicense() {
+		return bussinessLicense;
+	}
+	
+	public void setBussinessLicense(String bussinessLicense) {
+		this.bussinessLicense = bussinessLicense;
+	}
+	
+	public String getBankAccount() {
+		return bankAccount;
+	}
+	
+	public void setBankAccount(String bankAccount) {
+		this.bankAccount = bankAccount;
+	}
+	
+	public String getEmployeeNumber() {
+		return employeeNumber;
+	}
+	
+	public void setEmployeeNumber(String employeeNumber) {
+		this.employeeNumber = employeeNumber;
+	}
+	
+	public String getPurchaserNumber() {
+		return purchaserNumber;
+	}
+	
+	public void setPurchaserNumber(String purchaserNumber) {
+		this.purchaserNumber = purchaserNumber;
+	}
+	
+	public String getSeniorProfessionalPostNumber() {
+		return seniorProfessionalPostNumber;
+	}
+	
+	public void setSeniorProfessionalPostNumber(String seniorProfessionalPostNumber) {
+		this.seniorProfessionalPostNumber = seniorProfessionalPostNumber;
+	}
+	
+	public String getMediumProfessionalPostNumber() {
+		return mediumProfessionalPostNumber;
+	}
+	
+	public void setMediumProfessionalPostNumber(String mediumProfessionalPostNumber) {
+		this.mediumProfessionalPostNumber = mediumProfessionalPostNumber;
+	}
+	
+	public String getPrimaryProfessionalPostNumber() {
+		return primaryProfessionalPostNumber;
+	}
+	
+	public void setPrimaryProfessionalPostNumber(String primaryProfessionalPostNumber) {
+		this.primaryProfessionalPostNumber = primaryProfessionalPostNumber;
+	}
+	
+	public String getArtisanNumber() {
+		return artisanNumber;
+	}
+	
+	public void setArtisanNumber(String artisanNumber) {
+		this.artisanNumber = artisanNumber;
+	}
+	
+	public String getBusinessScope() {
+		return businessScope;
+	}
+	
+	public void setBusinessScope(String businessScope) {
+		this.businessScope = businessScope;
+	}
+	
+	public String getEnterpriseNature() {
+		return enterpriseNature;
+	}
+	
+	public void setEnterpriseNature(String enterpriseNature) {
+		this.enterpriseNature = enterpriseNature;
+	}
+	
+	public String getEquityStructure() {
+		return equityStructure;
+	}
+	
+	public void setEquityStructure(String equityStructure) {
+		this.equityStructure = equityStructure;
+	}
+	
+	public String getRelatedCompanyInfo() {
+		return relatedCompanyInfo;
+	}
+	
+	public void setRelatedCompanyInfo(String relatedCompanyInfo) {
+		this.relatedCompanyInfo = relatedCompanyInfo;
+	}
+	
+	public String getServiceAbility() {
+		return serviceAbility;
+	}
+	
+	public void setServiceAbility(String serviceAbility) {
+		this.serviceAbility = serviceAbility;
+	}
+	
+	public String getPreInputDevice() {
+		return preInputDevice;
+	}
+	
+	public void setPreInputDevice(String preInputDevice) {
+		this.preInputDevice = preInputDevice;
+	}
+	
+	public String getMemo() {
+		return memo;
+	}
+	
+	public void setMemo(String memo) {
+		this.memo = memo;
+	}
+	
+	public String getCompanyName() {
+		return companyName;
+	}
+	
+	public void setCompanyName(String companyName) {
+		this.companyName = companyName;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/BusinessLicense.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/BusinessLicense.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce97142f686ef40fdff08ee80aa17094da399b57
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/BusinessLicense.java
@@ -0,0 +1,202 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class BusinessLicense {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 模型数据ID
+	 */
+	private String modelDataId;
+	/**
+	 * 统一社会信用代码
+	 */
+	private String registerNumber;
+	/**
+	 * 企业名称
+	 */
+	private String companyName;
+	/**
+	 * 法定代表人
+	 */
+	private String legalRepresentative;
+	/**
+	 * 注册资本(万元)
+	 */
+	private String registerCapital;
+	/**
+	 * 住所
+	 */
+	private String companyAddress;
+	/**
+	 * 是否区内企业
+	 */
+	private String isInAreaEnterprises;
+	/**
+	 * 登记机关
+	 */
+	private String registerInstitution;
+	/**
+	 * 成立日期
+	 */
+	private String establishDate;
+	/**
+	 * 营业期限起
+	 */
+	private String busnissTermStartDate;
+	/**
+	 * 营业期限止
+	 */
+	private String busnissTermEndtDate;
+	/**
+	 * 营业范围
+	 */
+	private String businessScope;
+	/**
+	 * 类型
+	 */
+	private String companyType;
+	/**
+	 * 是否为永久经营
+	 */
+	private String isPerpetual;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getModelDataId() {
+		return modelDataId;
+	}
+	
+	public void setModelDataId(String modelDataId) {
+		this.modelDataId = modelDataId;
+	}
+	
+	public String getRegisterNumber() {
+		return registerNumber;
+	}
+	
+	public void setRegisterNumber(String registerNumber) {
+		this.registerNumber = registerNumber;
+	}
+	
+	public String getCompanyName() {
+		return companyName;
+	}
+	
+	public void setCompanyName(String companyName) {
+		this.companyName = companyName;
+	}
+	
+	public String getLegalRepresentative() {
+		return legalRepresentative;
+	}
+	
+	public void setLegalRepresentative(String legalRepresentative) {
+		this.legalRepresentative = legalRepresentative;
+	}
+	
+	public String getRegisterCapital() {
+		return registerCapital;
+	}
+	
+	public void setRegisterCapital(String registerCapital) {
+		this.registerCapital = registerCapital;
+	}
+	
+	public String getCompanyAddress() {
+		return companyAddress;
+	}
+	
+	public void setCompanyAddress(String companyAddress) {
+		this.companyAddress = companyAddress;
+	}
+	
+	public String getIsInAreaEnterprises() {
+		return isInAreaEnterprises;
+	}
+	
+	public void setIsInAreaEnterprises(String isInAreaEnterprises) {
+		this.isInAreaEnterprises = isInAreaEnterprises;
+	}
+	
+	public String getRegisterInstitution() {
+		return registerInstitution;
+	}
+	
+	public void setRegisterInstitution(String registerInstitution) {
+		this.registerInstitution = registerInstitution;
+	}
+	
+	public String getEstablishDate() {
+		return establishDate;
+	}
+	
+	public void setEstablishDate(String establishDate) {
+		this.establishDate = establishDate;
+	}
+	
+	public String getBusnissTermStartDate() {
+		return busnissTermStartDate;
+	}
+	
+	public void setBusnissTermStartDate(String busnissTermStartDate) {
+		this.busnissTermStartDate = busnissTermStartDate;
+	}
+	
+	public String getBusnissTermEndtDate() {
+		return busnissTermEndtDate;
+	}
+	
+	public void setBusnissTermEndtDate(String busnissTermEndtDate) {
+		this.busnissTermEndtDate = busnissTermEndtDate;
+	}
+	
+	public String getBusinessScope() {
+		return businessScope;
+	}
+	
+	public void setBusinessScope(String businessScope) {
+		this.businessScope = businessScope;
+	}
+	
+	public String getCompanyType() {
+		return companyType;
+	}
+	
+	public void setCompanyType(String companyType) {
+		this.companyType = companyType;
+	}
+	
+	public String getIsPerpetual() {
+		return isPerpetual;
+	}
+	
+	public void setIsPerpetual(String isPerpetual) {
+		this.isPerpetual = isPerpetual;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/CashSheet.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/CashSheet.java
new file mode 100644
index 0000000000000000000000000000000000000000..51123a063924264fb5dad7d0bccd9efdd6508ba5
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/CashSheet.java
@@ -0,0 +1,60 @@
+package com.gx.obe.struct.beans;
+
+import java.math.BigDecimal;
+
+/**
+ * @Description: 现金流量表
+ * @author chenxw
+ */
+public class CashSheet {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 财务ID
+	 */
+	private String financeId;
+	/**
+	 * 经营净现金流量
+	 */
+	private BigDecimal operatingNetCashFlow;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getFinanceId() {
+		return financeId;
+	}
+	
+	public void setFinanceId(String financeId) {
+		this.financeId = financeId;
+	}
+	
+	public BigDecimal getOperatingNetCashFlow() {
+		return operatingNetCashFlow;
+	}
+	
+	public void setOperatingNetCashFlow(BigDecimal operatingNetCashFlow) {
+		this.operatingNetCashFlow = operatingNetCashFlow;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/Certificate.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Certificate.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c41bd575a553a40bf853b586de6f81766990b7f
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Certificate.java
@@ -0,0 +1,94 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class Certificate {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 项目负责人ID
+	 */
+	private String projectLeaderId;
+	/**
+	 * 证书编号
+	 */
+	private String certificateNo;
+	/**
+	 * 证书名称
+	 */
+	private String certificateName;
+	/**
+	 * 证书等级
+	 */
+	private String certificateLevel;
+	/**
+	 * 序号
+	 */
+	private Integer sortNo;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getProjectLeaderId() {
+		return projectLeaderId;
+	}
+	
+	public void setProjectLeaderId(String projectLeaderId) {
+		this.projectLeaderId = projectLeaderId;
+	}
+	
+	public String getCertificateName() {
+		return certificateName;
+	}
+	
+	public void setCertificateName(String certificateName) {
+		this.certificateName = certificateName;
+	}
+	
+	public Integer getSortNo() {
+		return sortNo;
+	}
+	
+	public void setSortNo(Integer sortNo) {
+		this.sortNo = sortNo;
+	}
+	
+	public String getCertificateNo() {
+		return certificateNo;
+	}
+	
+	public void setCertificateNo(String certificateNo) {
+		this.certificateNo = certificateNo;
+	}
+	
+	public String getCertificateLevel() {
+		return certificateLevel;
+	}
+	
+	public void setCertificateLevel(String certificateLevel) {
+		this.certificateLevel = certificateLevel;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/ConditionDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ConditionDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..87d40423acefdc80f0886486141cfdc50e3acf12
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ConditionDO.java
@@ -0,0 +1,101 @@
+package com.gx.obe.struct.beans;
+
+public class ConditionDO {
+	
+	/**
+	 * @Description: 下限
+	 */
+	private String minRate;
+	
+	/**
+	 * @Description: 下限符: 00 小于 01小于等于
+	 */
+	private String minInclude;
+	
+	/**
+	 * @Description: 上限
+	 */
+	private String maxRate;
+	
+	/**
+	 * @Description: 上限符: 00 大于 01大于等于
+	 */
+	private String maxInclude;
+	
+//	<!--大于起始整数绝对值计量单位数量-->
+	private String maxEqRate;
+//	 <!--计量单位得分-->
+	private String value;
+	
+	private String awardLevel;
+	
+	public String getMaxEqRate() {
+		return maxEqRate;
+	}
+
+	public void setMaxEqRate(String maxEqRate) {
+		this.maxEqRate = maxEqRate;
+	}
+
+	public String getValue() {
+		return value;
+	}
+
+	public void setValue(String value) {
+		this.value = value;
+	}
+
+	public String getAwardLevel() {
+		return awardLevel;
+	}
+
+	public void setAwardLevel(String awardLevel) {
+		this.awardLevel = awardLevel;
+	}
+
+	/**
+	 * @Description: 得分
+	 */
+	private String score;
+	
+	public String getMinRate() {
+		return minRate;
+	}
+	
+	public void setMinRate(String minRate) {
+		this.minRate = minRate;
+	}
+	
+	public String getMinInclude() {
+		return minInclude;
+	}
+	
+	public void setMinInclude(String minInclude) {
+		this.minInclude = minInclude;
+	}
+	
+	public String getMaxRate() {
+		return maxRate;
+	}
+	
+	public void setMaxRate(String maxRate) {
+		this.maxRate = maxRate;
+	}
+	
+	public String getMaxInclude() {
+		return maxInclude;
+	}
+	
+	public void setMaxInclude(String maxInclude) {
+		this.maxInclude = maxInclude;
+	}
+	
+	public String getScore() {
+		return score;
+	}
+	
+	public void setScore(String score) {
+		this.score = score;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/CustomModelDo.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/CustomModelDo.java
new file mode 100644
index 0000000000000000000000000000000000000000..da9f80821912d33e64e6541728ecc96ccd42ea2e
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/CustomModelDo.java
@@ -0,0 +1,54 @@
+package com.gx.obe.struct.beans;
+
+public class CustomModelDo {
+	
+	/**
+	 * @Description: 序号id
+	 */
+	private String id;
+	/**
+	 * @Description: 得分
+	 */
+	private String score;
+	/**
+	 * @Description: 描述
+	 */
+	private String description;
+	/**
+	 * @Description: 备注
+	 */
+	private String remarks;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getScore() {
+		return score;
+	}
+	
+	public void setScore(String score) {
+		this.score = score;
+	}
+	
+	public String getDescription() {
+		return description;
+	}
+	
+	public void setDescription(String description) {
+		this.description = description;
+	}
+	
+	public String getRemarks() {
+		return remarks;
+	}
+	
+	public void setRemarks(String remarks) {
+		this.remarks = remarks;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/Finance.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Finance.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9fde9bd994f6b0343540537b38fa190db96b456
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Finance.java
@@ -0,0 +1,372 @@
+package com.gx.obe.struct.beans;
+
+import java.math.BigDecimal;
+
+/**
+ * @Description: 财务报表
+ * @author chenxw
+ */
+public class Finance {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 模型数据ID
+	 */
+	private String modelDataId;
+	/**
+	 * 年度
+	 */
+	private String annual;
+	/**
+	 * 注册资本
+	 */
+//	private BigDecimal registeredCapital;
+	/**
+	 * 总资产(万元)
+	 */
+	private BigDecimal total;
+	/**
+	 * 利润总额(万元)
+	 */
+	private BigDecimal profitLossProfit;
+	/**
+	 * 营业收入(万元)
+	 */
+	private BigDecimal operatingIncome;
+	/**
+	 * 资产负债率(%)
+	 */
+	private BigDecimal liabilitiesRate;
+	/**
+	 * 流动资产(万元)
+	 */
+	private BigDecimal currentAssets;
+	/**
+	 * 流动负债(万元)
+	 */
+	private BigDecimal currentLiabilities;
+	/**
+	 * 流动比率(%)
+	 */
+	private BigDecimal currentRate;
+	/**
+	 * 净利率(%)
+	 */
+	private BigDecimal profitRatio;
+	/**
+	 * 主营业务利润率(%)
+	 */
+	private BigDecimal operatingMargin;
+	/**
+	 * 净利润(万元)
+	 */
+	private BigDecimal retainedProfits;
+	/**
+	 * 企业名称
+	 */
+	private String companyName;
+	/**
+	 * 净资产(万元)
+	 */
+	private BigDecimal netWorth;
+	/**
+	 * 固定资产(万元)
+	 */
+//	private BigDecimal fixedAssets;
+	/**
+	 * 现金流量净额(万元)
+	 */
+//	private BigDecimal netCashFlow;
+	/**
+	 * 净资产收益率(%)
+	 */
+//	private BigDecimal returnOnEquity;
+	/**
+	 * 总资产报酬率(%)
+	 */
+//	private BigDecimal returnOnTotalAsset;
+	/**
+	 * 速动比率(%)
+	 */
+	private BigDecimal quickRatio;
+	/**
+	 * 负债合计(万元)
+	 */
+	private BigDecimal totalliabilities;
+	/**
+	 * 成本费用总额(万元)
+	 */
+	private BigDecimal totalcost;
+	/**
+	 * 速动资产(万元)
+	 */
+	private BigDecimal quickassets;
+	/**
+	 * 主营业务利润(万元)
+	 */
+	private BigDecimal mainIncomeProfits;
+	/**
+	 * 主营业务收入(万元)
+	 */
+	private BigDecimal primeOperatingRevenue;
+	/**
+	 * 资产负债表
+	 */
+//	private BalanceSheet balanceSheet;
+	/**
+	 * 损益表
+	 */
+//	private ProfitlossSheet profitlossSheet;
+	/**
+	 * 现金流量表
+	 */
+//	private CashSheet cashSheet;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getModelDataId() {
+		return modelDataId;
+	}
+	
+	public void setModelDataId(String modelDataId) {
+		this.modelDataId = modelDataId;
+	}
+	
+	public String getAnnual() {
+		return annual;
+	}
+	
+	public void setAnnual(String annual) {
+		this.annual = annual;
+	}
+	
+	public BigDecimal getTotal() {
+		return total;
+	}
+	
+	public void setTotal(BigDecimal total) {
+		this.total = total;
+	}
+	
+	public BigDecimal getOperatingIncome() {
+		return operatingIncome;
+	}
+	
+	public void setOperatingIncome(BigDecimal operatingIncome) {
+		this.operatingIncome = operatingIncome;
+	}
+	
+	public BigDecimal getLiabilitiesRate() {
+		return liabilitiesRate;
+	}
+	
+	public void setLiabilitiesRate(BigDecimal liabilitiesRate) {
+		this.liabilitiesRate = liabilitiesRate;
+	}
+	
+	public BigDecimal getCurrentAssets() {
+		return currentAssets;
+	}
+	
+	public void setCurrentAssets(BigDecimal currentAssets) {
+		this.currentAssets = currentAssets;
+	}
+	
+	public BigDecimal getCurrentLiabilities() {
+		return currentLiabilities;
+	}
+	
+	public void setCurrentLiabilities(BigDecimal currentLiabilities) {
+		this.currentLiabilities = currentLiabilities;
+	}
+	
+	public BigDecimal getCurrentRate() {
+		return currentRate;
+	}
+	
+	public void setCurrentRate(BigDecimal currentRate) {
+		this.currentRate = currentRate;
+	}
+	
+	public BigDecimal getOperatingMargin() {
+		return operatingMargin;
+	}
+	
+	public void setOperatingMargin(BigDecimal operatingMargin) {
+		this.operatingMargin = operatingMargin;
+	}
+	
+	public BigDecimal getRetainedProfits() {
+		return retainedProfits;
+	}
+	
+	public void setRetainedProfits(BigDecimal retainedProfits) {
+		this.retainedProfits = retainedProfits;
+	}
+	
+	public String getCompanyName() {
+		return companyName;
+	}
+	
+	public void setCompanyName(String companyName) {
+		this.companyName = companyName;
+	}
+	
+	public BigDecimal getNetWorth() {
+		return netWorth;
+	}
+	
+	public void setNetWorth(BigDecimal netWorth) {
+		this.netWorth = netWorth;
+	}
+	
+//	public BigDecimal getFixedAssets() {
+//		return fixedAssets;
+//	}
+//	
+//	public void setFixedAssets(BigDecimal fixedAssets) {
+//		this.fixedAssets = fixedAssets;
+//	}
+//	
+//	public BigDecimal getNetCashFlow() {
+//		return netCashFlow;
+//	}
+//	
+//	public void setNetCashFlow(BigDecimal netCashFlow) {
+//		this.netCashFlow = netCashFlow;
+//	}
+//	
+//	public BigDecimal getReturnOnEquity() {
+//		return returnOnEquity;
+//	}
+//	
+//	public void setReturnOnEquity(BigDecimal returnOnEquity) {
+//		this.returnOnEquity = returnOnEquity;
+//	}
+//	
+//	public BigDecimal getReturnOnTotalAsset() {
+//		return returnOnTotalAsset;
+//	}
+//	
+//	public void setReturnOnTotalAsset(BigDecimal returnOnTotalAsset) {
+//		this.returnOnTotalAsset = returnOnTotalAsset;
+//	}
+	
+	public BigDecimal getQuickRatio() {
+		return quickRatio;
+	}
+	
+	public void setQuickRatio(BigDecimal quickRatio) {
+		this.quickRatio = quickRatio;
+	}
+	
+	public BigDecimal getTotalliabilities() {
+		return totalliabilities;
+	}
+	
+	public void setTotalliabilities(BigDecimal totalliabilities) {
+		this.totalliabilities = totalliabilities;
+	}
+	
+//	public BalanceSheet getBalanceSheet() {
+//		return balanceSheet;
+//	}
+//	
+//	public void setBalanceSheet(BalanceSheet balanceSheet) {
+//		this.balanceSheet = balanceSheet;
+//	}
+//	
+//	public ProfitlossSheet getProfitlossSheet() {
+//		return profitlossSheet;
+//	}
+//	
+//	public void setProfitlossSheet(ProfitlossSheet profitlossSheet) {
+//		this.profitlossSheet = profitlossSheet;
+//	}
+//	
+//	public CashSheet getCashSheet() {
+//		return cashSheet;
+//	}
+//	
+//	public void setCashSheet(CashSheet cashSheet) {
+//		this.cashSheet = cashSheet;
+//	}
+	
+//	public BigDecimal getRegisteredCapital() {
+//		return registeredCapital;
+//	}
+//	
+//	public void setRegisteredCapital(BigDecimal registeredCapital) {
+//		this.registeredCapital = registeredCapital;
+//	}
+	
+	public BigDecimal getTotalcost() {
+		return totalcost;
+	}
+	
+	public void setTotalcost(BigDecimal totalcost) {
+		this.totalcost = totalcost;
+	}
+	
+	public BigDecimal getQuickassets() {
+		return quickassets;
+	}
+	
+	public void setQuickassets(BigDecimal quickassets) {
+		this.quickassets = quickassets;
+	}
+	
+	public BigDecimal getMainIncomeProfits() {
+		return mainIncomeProfits;
+	}
+	
+	public void setMainIncomeProfits(BigDecimal mainIncomeProfits) {
+		this.mainIncomeProfits = mainIncomeProfits;
+	}
+
+	public BigDecimal getPrimeOperatingRevenue() {
+		return primeOperatingRevenue;
+	}
+
+	public void setPrimeOperatingRevenue(BigDecimal primeOperatingRevenue) {
+		this.primeOperatingRevenue = primeOperatingRevenue;
+	}
+
+	public BigDecimal getProfitLossProfit() {
+		return profitLossProfit;
+	}
+
+	public void setProfitLossProfit(BigDecimal profitLossProfit) {
+		this.profitLossProfit = profitLossProfit;
+	}
+
+	public BigDecimal getProfitRatio() {
+		return profitRatio;
+	}
+
+	public void setProfitRatio(BigDecimal profitRatio) {
+		this.profitRatio = profitRatio;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/IntelligentEvalDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/IntelligentEvalDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..8e5386010cedf559f66e83505d02eba9a5e740be
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/IntelligentEvalDO.java
@@ -0,0 +1,244 @@
+package com.gx.obe.struct.beans;
+
+import java.util.List;
+
+import com.gx.obe.http.json.JsonUtil;
+
+/**
+ * 评审指标结构化区域
+ * @author gnauh
+ *
+ */
+public class IntelligentEvalDO {
+	
+	/**
+	 * @Description: 供应商问题描述
+	 */
+//	private String supplierQuestion;
+	/**
+	 * @Description: 是否需要上传附件 00不需要 01 需要
+	 */
+//	private String isMustBoundFile;
+	/**
+	 * @Description: 指标来源 供应商响应:A ,系统采集:B ,供应商响应时:指标内容只能是99无,指标模型可不考虑;系统采集时:指标内容不能是99无,指标模型必选;
+	 */
+//	private String factorSource;
+	/**
+	 * @Description: 指标内容 01 注册资金、02 履约异常、03同业业绩、04 全部业绩、05 合格率、06 供应商等级、07使用质量、08 交付履约绩效、99 其它类型
+	 */
+	private String factorType;
+	/**
+	 * @Description: 区间模型 05 时间模型06 升降率模型 07 否决项模型 08
+	 */
+	private String factorModel;
+	/**
+	 * @Description: 评审指标代码 指标模型+指标来源+指标内容+四位流水码
+	 */
+	private String factorCode;
+	/**
+	 * @Description: 开始日期
+	 */
+//	private String startDate;
+	/**
+	 * @Description: 结束日期
+	 */
+//	private String endDate;
+	/**
+	 * @Description: 单位 万元01,个02
+	 */
+//	private String unit;
+	/**
+	 * @Description: 单位 万元01,个02
+	 */
+//	private String unitCode;
+//	/**
+//	 * @Description: 类型说明是否项:是 01,否 00
+//	 */
+//	private String correctResult;
+	/**
+	 * @Description: 评审模型描述
+	 */
+//	private String intelligentEvalRemark;
+	/**
+	 * @Description: 区间列表
+	 */
+	private List<ConditionDO> conditionList;
+//	/**
+//	 * @Description: 时间模型
+//	 */
+//	private TimeModelDO timeModel;
+	/**
+	 * @Description: 升降率模型
+	 */
+	private LiftRateDO liftRate;
+	
+	private List<ScoreOptionsDO> scoreOptionsDOList;
+//	/**
+//	 * @Description: 否决项模型
+//	 */
+//	private VoteModelDO voteModel;
+//	/**
+//	 * @Description: 自定义模型
+//	 */
+//	private List<CustomModelDo> customModelList;
+	
+	public String toJson() {
+		return JsonUtil.jsonObjectToStr(this);
+	}
+	
+//	public String getSupplierQuestion() {
+//		return supplierQuestion;
+//	}
+//	
+//	public void setSupplierQuestion(String supplierQuestion) {
+//		this.supplierQuestion = supplierQuestion;
+//	}
+	
+//	public String getIsMustBoundFile() {
+//		return isMustBoundFile;
+//	}
+//	
+//	public void setIsMustBoundFile(String isMustBoundFile) {
+//		this.isMustBoundFile = isMustBoundFile;
+//	}
+	
+//	public String getFactorSource() {
+//		return factorSource;
+//	}
+//	
+//	public void setFactorSource(String factorSource) {
+//		this.factorSource = factorSource;
+//	}
+	
+	private AbsoluteModelDO absoluteModelDO;
+	
+	public AbsoluteModelDO getAbsoluteModelDO() {
+		return absoluteModelDO;
+	}
+
+	public void setAbsoluteModelDO(AbsoluteModelDO absoluteModelDO) {
+		this.absoluteModelDO = absoluteModelDO;
+	}
+
+	public String getFactorType() {
+		return factorType;
+	}
+	
+	public void setFactorType(String factorType) {
+		this.factorType = factorType;
+	}
+	
+	public String getFactorModel() {
+		return factorModel;
+	}
+	
+	public void setFactorModel(String factorModel) {
+		this.factorModel = factorModel;
+	}
+	
+	public String getFactorCode() {
+		return factorCode;
+	}
+	
+	public void setFactorCode(String factorCode) {
+		this.factorCode = factorCode;
+	}
+	
+//	public String getStartDate() {
+//		return startDate;
+//	}
+//	
+//	public void setStartDate(String startDate) {
+//		this.startDate = startDate;
+//	}
+	
+//	public String getEndDate() {
+//		return endDate;
+//	}
+//	
+//	public void setEndDate(String endDate) {
+//		this.endDate = endDate;
+//	}
+//	
+//	public String getUnit() {
+//		return unit;
+//	}
+//	
+//	public void setUnit(String unit) {
+//		this.unit = unit;
+//	}
+//	
+//	public String getUnitCode() {
+//		return unitCode;
+//	}
+//	
+//	public void setUnitCode(String unitCode) {
+//		this.unitCode = unitCode;
+//	}
+	
+	public List<ConditionDO> getConditionList() {
+		return conditionList;
+	}
+	
+	public void setConditionList(List<ConditionDO> conditionList) {
+		this.conditionList = conditionList;
+	}
+	
+
+	public List<ScoreOptionsDO> getScoreOptionsDOList() {
+		return scoreOptionsDOList;
+	}
+
+	public void setScoreOptionsDOList(List<ScoreOptionsDO> scoreOptionsDOList) {
+		this.scoreOptionsDOList = scoreOptionsDOList;
+	}
+
+	//	public TimeModelDO getTimeModel() {
+//		return timeModel;
+//	}
+//	
+//	public void setTimeModel(TimeModelDO timeModel) {
+//		this.timeModel = timeModel;
+//	}
+//	
+	public LiftRateDO getLiftRate() {
+		return liftRate;
+	}
+	
+	public void setLiftRate(LiftRateDO liftRate) {
+		this.liftRate = liftRate;
+	}
+	
+//	public VoteModelDO getVoteModel() {
+//		return voteModel;
+//	}
+//	
+//	public void setVoteModel(VoteModelDO voteModel) {
+//		this.voteModel = voteModel;
+//	}
+	
+//	public String getCorrectResult() {
+//		return correctResult;
+//	}
+//	
+//	public void setCorrectResult(String correctResult) {
+//		this.correctResult = correctResult;
+//	}
+	
+//	public String getIntelligentEvalRemark() {
+//		return intelligentEvalRemark;
+//	}
+//	
+//	public void setIntelligentEvalRemark(String intelligentEvalRemark) {
+//		this.intelligentEvalRemark = intelligentEvalRemark;
+//	}
+//	
+//	public List<CustomModelDo> getCustomModelList() {
+//		return customModelList;
+//	}
+//	
+//	public void setCustomModelList(List<CustomModelDo> customModelList) {
+//		this.customModelList = customModelList;
+//	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/LiftRateDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/LiftRateDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..bad418d094b9e4c0d3bf3059305f0a603df82efa
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/LiftRateDO.java
@@ -0,0 +1,159 @@
+package com.gx.obe.struct.beans;
+
+public class LiftRateDO {
+	
+	/**
+	 <liftRate>
+     <_responseType>排名</_responseType>
+     <sort>1</sort>
+     <Score>5</Score>
+     <MinScore>0</MinScore>
+     <MaxScore>5</MaxScore>
+     <responseType>01</responseType>
+     <typeNote>01</typeNote>
+     <_typeNote>高名次</_typeNote>
+     <ranking>1</ranking>
+     <dealType>01</dealType>
+     <_dealType>投标人响应值最高为第一名</_dealType>
+     <dealScore />
+     <unit>%</unit>
+     <decimalDigits>6</decimalDigits>
+    </liftRate>
+    */
+	/**
+	 * @Description: 响应类型: 排名 01、百分比 02、出现次数 03
+	 */
+	private String responseType;
+	/**
+	 * @Description: 类型说明:高名次 01、低名次 02
+	 */
+	private String typeNote;
+	/**
+	 * @Description: 名次:整形
+	 */
+	private String ranking;
+	/**
+	 * @Description: 处理类型:加分01 、扣分 02
+	 */
+	private String dealType;
+	/**
+	 * @Description: 处理分数:可填
+	 */
+	private String dealScore;
+	/**
+	 * @Description: 备注:可填
+	 */
+	private String memo;
+	private String sort;
+	private String Score;
+	private String minScore;
+	private String maxScore;
+	
+	/**
+	 * 单位
+	 */
+	private String unit;
+	/**
+	 * 小数点位数
+	 */
+	private String decimalDigits;
+	
+	public String getResponseType() {
+		return responseType;
+	}
+	
+	public void setResponseType(String responseType) {
+		this.responseType = responseType;
+	}
+	
+	public String getTypeNote() {
+		return typeNote;
+	}
+	
+	public void setTypeNote(String typeNote) {
+		this.typeNote = typeNote;
+	}
+	
+	public String getRanking() {
+		return ranking;
+	}
+	
+	public void setRanking(String ranking) {
+		this.ranking = ranking;
+	}
+	
+	public String getDealType() {
+		return dealType;
+	}
+	
+	public void setDealType(String dealType) {
+		this.dealType = dealType;
+	}
+	
+	public String getDealScore() {
+		return dealScore;
+	}
+	
+	public void setDealScore(String dealScore) {
+		this.dealScore = dealScore;
+	}
+	
+	public String getMemo() {
+		return memo;
+	}
+	
+	public void setMemo(String memo) {
+		this.memo = memo;
+	}
+
+	public String getSort() {
+		return sort;
+	}
+
+	public void setSort(String sort) {
+		this.sort = sort;
+	}
+
+	public String getScore() {
+		return Score;
+	}
+
+	public void setScore(String score) {
+		Score = score;
+	}
+
+	public String getUnit() {
+		return unit;
+	}
+
+	public void setUnit(String unit) {
+		this.unit = unit;
+	}
+
+	public String getDecimalDigits() {
+		return decimalDigits;
+	}
+
+	public void setDecimalDigits(String decimalDigits) {
+		this.decimalDigits = decimalDigits;
+	}
+
+	public String getMinScore() {
+		return minScore;
+	}
+
+	public void setMinScore(String minScore) {
+		this.minScore = minScore;
+	}
+
+	public String getMaxScore() {
+		return maxScore;
+	}
+
+	public void setMaxScore(String maxScore) {
+		this.maxScore = maxScore;
+	}
+
+	
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/ModelData.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ModelData.java
new file mode 100644
index 0000000000000000000000000000000000000000..66abe5453b505b4c7ef45d4a68e2d7e9ce7ec5fa
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ModelData.java
@@ -0,0 +1,54 @@
+package com.gx.obe.struct.beans;
+
+/** 
+ * @Description: 对象结构化数据
+ * @author chenxw 
+ */
+public class ModelData {
+	
+	private String id;
+	private String tenderId;
+	private String supplierId;
+	private String relChapterType;
+	private String dataCode;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getSupplierId() {
+		return supplierId;
+	}
+	
+	public void setSupplierId(String supplierId) {
+		this.supplierId = supplierId;
+	}
+	
+	public String getRelChapterType() {
+		return relChapterType;
+	}
+	
+	public void setRelChapterType(String relChapterType) {
+		this.relChapterType = relChapterType;
+	}
+	
+	public String getDataCode() {
+		return dataCode;
+	}
+	
+	public void setDataCode(String dataCode) {
+		this.dataCode = dataCode;
+	}
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/ParamValueDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ParamValueDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f1fc46870bb7e6fd82431ea9b883ea0d333e9a6
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ParamValueDO.java
@@ -0,0 +1,32 @@
+package com.gx.obe.struct.beans;
+
+public class ParamValueDO {
+
+    //<!--数据Code 如财务报告中的主营业务利润等资质证明文件的类型 如:EQ_FinancialReport,也包括后续扩展有具体含义的数据Code -->
+	private String dataCode;
+	//	<!--数据类型 string字符串  number数字 投标管家对于无具体含义填空时使用  -->
+	private String dataType;
+	//	<!--具体的响应值,如果是资质证明文件类型数据这里就是对于资质的数据文件 如:Finance.xml,如果是选项模型的这里保存的是选项的Id,其他的是投标人填写的对应的值。 -->
+	private String dataValue;
+	
+	public String getDataCode() {
+		return dataCode;
+	}
+	public void setDataCode(String dataCode) {
+		this.dataCode = dataCode;
+	}
+	public String getDataType() {
+		return dataType;
+	}
+	public void setDataType(String dataType) {
+		this.dataType = dataType;
+	}
+	public String getDataValue() {
+		return dataValue;
+	}
+	public void setDataValue(String dataValue) {
+		this.dataValue = dataValue;
+	}
+	
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/Performance.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Performance.java
new file mode 100644
index 0000000000000000000000000000000000000000..019e310c30fed9d1103f9f16afc88fa08c08c552
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Performance.java
@@ -0,0 +1,658 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class Performance {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 模型数据ID
+	 */
+	private String modelDataId;
+	/**
+	 * 采购单位
+	 */
+	private String purchasingUnit;
+	/**
+	 * 供货单位
+	 */
+	private String partner;
+	/**
+	 * 项目名称
+	 */
+	private String projectName;
+	/**
+	 * 签订日期
+	 */
+	private String singningDate;
+	/**
+	 * 结束日期
+	 */
+	private String endTime;
+	/**
+	 * 合同金额(单位:元)
+	 */
+	private String singningTotal;
+	/**
+	 * 项目经理姓名
+	 */
+	private String purchaser;
+	/**
+	 * 代表联系电话
+	 */
+	private String purchaserPhone;
+	/**
+	 * 业绩状态(00:进行中;01:已完成)
+	 */
+	private String status;
+	/**
+	 * 企业名称
+	 */
+	private String supplierName;
+	/**
+	 * 项目所在地
+	 */
+	private String projectAddress;
+	/**
+	 * 发包人名称
+	 */
+	private String buyerName;
+	/**
+	 * 发包人地址
+	 */
+	private String buyerAddress;
+	/**
+	 * 发包人电话
+	 */
+	private String buyerPhoneNumber;
+	/**
+	 * 开工日期
+	 */
+	private String startTime;
+	/**
+	 * 承担的工作
+	 */
+	private String workUndertaken;
+	/**
+	 * 工程质量
+	 */
+	private String projectQuantity;
+	/**
+	 * 项目经理
+	 */
+	private String projectManager;
+	/**
+	 * 技术负责人
+	 */
+	private String technicalDirector;
+	/**
+	 * 总监理工程师
+	 */
+	private String chiefSupervisionEngineer;
+	/**
+	 * 总监理工程师电话
+	 */
+	private String csePhoneNumber;
+	/**
+	 * 项目描述
+	 */
+	private String projectDesc;
+	/**
+	 * 调试范围及内容
+	 */
+	private String projectRangeAndContent;
+	/**
+	 * 调试机构人数高峰
+	 */
+	private String supplierWorkerCountmax;
+	/**
+	 * 调试机构人数平均
+	 */
+	private String supplierWorkerCountave;
+	/**
+	 * 工程评定情况
+	 */
+	private String projectDeviceResult;
+	/**
+	 * 项目单位联系人
+	 */
+	private String buyerLinkman;
+	/**
+	 * 是否附证明文件
+	 */
+	private String isHavrAccessory;
+	/**
+	 * 是否为华能系统的项目
+	 */
+	private String isOurCompanyProject;
+	/**
+	 * 服务范围
+	 */
+	private String serviceScope;
+	/**
+	 * 设备名称
+	 */
+	private String deviceName;
+	/**
+	 * 型号和规格
+	 */
+	private String devicetypeSpecification;
+	/**
+	 * 总容量
+	 */
+	private String totalCapacity;
+	/**
+	 * 台数
+	 */
+	private String number;
+	/**
+	 * 合同时间
+	 */
+	private String contractTime;
+	/**
+	 * 投运时间
+	 */
+	private String commissioningTime;
+	/**
+	 * 备注
+	 */
+	private String memo;
+	/**
+	 * 建设规模
+	 */
+	private String projectScale;
+	/**
+	 * 专业人员人数
+	 */
+	private String professionalNumber;
+	/**
+	 * 专业人员人月数
+	 */
+	private String professionalWorkload;
+	/**
+	 * 合作公司提供人员月数
+	 */
+	private String partnerProfessionalWorkload;
+	/**
+	 * 监理范围及内容
+	 */
+	private String supervisionCcontent;
+	/**
+	 * 监理效果
+	 */
+	private String supervisionResult;
+	/**
+	 * 关键人员姓名专业及职务
+	 */
+	private String keyStaffProfessionalAndDuty;
+	/**
+	 * 实际服务说明
+	 */
+	private String serviceDesc;
+	/**
+	 * 履约日期
+	 */
+	private String executionDate;
+	/**
+	 * 规模类型
+	 */
+	private String projectScaleAndType;
+	/**
+	 * 设计阶段
+	 */
+	private String designStage;
+	/**
+	 * 设计范围
+	 */
+	private String designRange;
+	/**
+	 * 合作方式
+	 */
+	private String cooperationWay;
+	/**
+	 * 合同履行获奖情况/合同履行情况
+	 */
+	private String contractExecuteCondition;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getModelDataId() {
+		return modelDataId;
+	}
+	
+	public void setModelDataId(String modelDataId) {
+		this.modelDataId = modelDataId;
+	}
+	
+	public String getPurchasingUnit() {
+		return purchasingUnit;
+	}
+	
+	public void setPurchasingUnit(String purchasingUnit) {
+		this.purchasingUnit = purchasingUnit;
+	}
+	
+	public String getPartner() {
+		return partner;
+	}
+	
+	public void setPartner(String partner) {
+		this.partner = partner;
+	}
+	
+	public String getProjectName() {
+		return projectName;
+	}
+	
+	public void setProjectName(String projectName) {
+		this.projectName = projectName;
+	}
+	
+	public String getSingningDate() {
+		return singningDate;
+	}
+	
+	public void setSingningDate(String singningDate) {
+		this.singningDate = singningDate;
+	}
+	
+	public String getEndTime() {
+		return endTime;
+	}
+	
+	public void setEndTime(String endTime) {
+		this.endTime = endTime;
+	}
+	
+	public String getSingningTotal() {
+		return singningTotal;
+	}
+	
+	public void setSingningTotal(String singningTotal) {
+		this.singningTotal = singningTotal;
+	}
+	
+	public String getPurchaser() {
+		return purchaser;
+	}
+	
+	public void setPurchaser(String purchaser) {
+		this.purchaser = purchaser;
+	}
+	
+	public String getPurchaserPhone() {
+		return purchaserPhone;
+	}
+	
+	public void setPurchaserPhone(String purchaserPhone) {
+		this.purchaserPhone = purchaserPhone;
+	}
+	
+	public String getStatus() {
+		return status;
+	}
+	
+	public void setStatus(String status) {
+		this.status = status;
+	}
+	
+	public String getSupplierName() {
+		return supplierName;
+	}
+	
+	public void setSupplierName(String supplierName) {
+		this.supplierName = supplierName;
+	}
+	
+	public String getProjectAddress() {
+		return projectAddress;
+	}
+	
+	public void setProjectAddress(String projectAddress) {
+		this.projectAddress = projectAddress;
+	}
+	
+	public String getBuyerName() {
+		return buyerName;
+	}
+	
+	public void setBuyerName(String buyerName) {
+		this.buyerName = buyerName;
+	}
+	
+	public String getBuyerAddress() {
+		return buyerAddress;
+	}
+	
+	public void setBuyerAddress(String buyerAddress) {
+		this.buyerAddress = buyerAddress;
+	}
+	
+	public String getBuyerPhoneNumber() {
+		return buyerPhoneNumber;
+	}
+	
+	public void setBuyerPhoneNumber(String buyerPhoneNumber) {
+		this.buyerPhoneNumber = buyerPhoneNumber;
+	}
+	
+	public String getStartTime() {
+		return startTime;
+	}
+	
+	public void setStartTime(String startTime) {
+		this.startTime = startTime;
+	}
+	
+	public String getWorkUndertaken() {
+		return workUndertaken;
+	}
+	
+	public void setWorkUndertaken(String workUndertaken) {
+		this.workUndertaken = workUndertaken;
+	}
+	
+	public String getProjectQuantity() {
+		return projectQuantity;
+	}
+	
+	public void setProjectQuantity(String projectQuantity) {
+		this.projectQuantity = projectQuantity;
+	}
+	
+	public String getProjectManager() {
+		return projectManager;
+	}
+	
+	public void setProjectManager(String projectManager) {
+		this.projectManager = projectManager;
+	}
+	
+	public String getTechnicalDirector() {
+		return technicalDirector;
+	}
+	
+	public void setTechnicalDirector(String technicalDirector) {
+		this.technicalDirector = technicalDirector;
+	}
+	
+	public String getChiefSupervisionEngineer() {
+		return chiefSupervisionEngineer;
+	}
+	
+	public void setChiefSupervisionEngineer(String chiefSupervisionEngineer) {
+		this.chiefSupervisionEngineer = chiefSupervisionEngineer;
+	}
+	
+	public String getCsePhoneNumber() {
+		return csePhoneNumber;
+	}
+	
+	public void setCsePhoneNumber(String csePhoneNumber) {
+		this.csePhoneNumber = csePhoneNumber;
+	}
+	
+	public String getProjectDesc() {
+		return projectDesc;
+	}
+	
+	public void setProjectDesc(String projectDesc) {
+		this.projectDesc = projectDesc;
+	}
+	
+	public String getProjectRangeAndContent() {
+		return projectRangeAndContent;
+	}
+	
+	public void setProjectRangeAndContent(String projectRangeAndContent) {
+		this.projectRangeAndContent = projectRangeAndContent;
+	}
+	
+	public String getSupplierWorkerCountmax() {
+		return supplierWorkerCountmax;
+	}
+	
+	public void setSupplierWorkerCountmax(String supplierWorkerCountmax) {
+		this.supplierWorkerCountmax = supplierWorkerCountmax;
+	}
+	
+	public String getSupplierWorkerCountave() {
+		return supplierWorkerCountave;
+	}
+	
+	public void setSupplierWorkerCountave(String supplierWorkerCountave) {
+		this.supplierWorkerCountave = supplierWorkerCountave;
+	}
+	
+	public String getProjectDeviceResult() {
+		return projectDeviceResult;
+	}
+	
+	public void setProjectDeviceResult(String projectDeviceResult) {
+		this.projectDeviceResult = projectDeviceResult;
+	}
+	
+	public String getBuyerLinkman() {
+		return buyerLinkman;
+	}
+	
+	public void setBuyerLinkman(String buyerLinkman) {
+		this.buyerLinkman = buyerLinkman;
+	}
+	
+	public String getIsHavrAccessory() {
+		return isHavrAccessory;
+	}
+	
+	public void setIsHavrAccessory(String isHavrAccessory) {
+		this.isHavrAccessory = isHavrAccessory;
+	}
+	
+	public String getIsOurCompanyProject() {
+		return isOurCompanyProject;
+	}
+	
+	public void setIsOurCompanyProject(String isOurCompanyProject) {
+		this.isOurCompanyProject = isOurCompanyProject;
+	}
+	
+	public String getServiceScope() {
+		return serviceScope;
+	}
+	
+	public void setServiceScope(String serviceScope) {
+		this.serviceScope = serviceScope;
+	}
+	
+	public String getDeviceName() {
+		return deviceName;
+	}
+	
+	public void setDeviceName(String deviceName) {
+		this.deviceName = deviceName;
+	}
+	
+	public String getDevicetypeSpecification() {
+		return devicetypeSpecification;
+	}
+	
+	public void setDevicetypeSpecification(String devicetypeSpecification) {
+		this.devicetypeSpecification = devicetypeSpecification;
+	}
+	
+	public String getTotalCapacity() {
+		return totalCapacity;
+	}
+	
+	public void setTotalCapacity(String totalCapacity) {
+		this.totalCapacity = totalCapacity;
+	}
+	
+	public String getNumber() {
+		return number;
+	}
+	
+	public void setNumber(String number) {
+		this.number = number;
+	}
+	
+	public String getContractTime() {
+		return contractTime;
+	}
+	
+	public void setContractTime(String contractTime) {
+		this.contractTime = contractTime;
+	}
+	
+	public String getCommissioningTime() {
+		return commissioningTime;
+	}
+	
+	public void setCommissioningTime(String commissioningTime) {
+		this.commissioningTime = commissioningTime;
+	}
+	
+	public String getMemo() {
+		return memo;
+	}
+	
+	public void setMemo(String memo) {
+		this.memo = memo;
+	}
+	
+	public String getProjectScale() {
+		return projectScale;
+	}
+	
+	public void setProjectScale(String projectScale) {
+		this.projectScale = projectScale;
+	}
+	
+	public String getProfessionalNumber() {
+		return professionalNumber;
+	}
+	
+	public void setProfessionalNumber(String professionalNumber) {
+		this.professionalNumber = professionalNumber;
+	}
+	
+	public String getProfessionalWorkload() {
+		return professionalWorkload;
+	}
+	
+	public void setProfessionalWorkload(String professionalWorkload) {
+		this.professionalWorkload = professionalWorkload;
+	}
+	
+	public String getPartnerProfessionalWorkload() {
+		return partnerProfessionalWorkload;
+	}
+	
+	public void setPartnerProfessionalWorkload(String partnerProfessionalWorkload) {
+		this.partnerProfessionalWorkload = partnerProfessionalWorkload;
+	}
+	
+	public String getSupervisionCcontent() {
+		return supervisionCcontent;
+	}
+	
+	public void setSupervisionCcontent(String supervisionCcontent) {
+		this.supervisionCcontent = supervisionCcontent;
+	}
+	
+	public String getSupervisionResult() {
+		return supervisionResult;
+	}
+	
+	public void setSupervisionResult(String supervisionResult) {
+		this.supervisionResult = supervisionResult;
+	}
+	
+	public String getKeyStaffProfessionalAndDuty() {
+		return keyStaffProfessionalAndDuty;
+	}
+	
+	public void setKeyStaffProfessionalAndDuty(String keyStaffProfessionalAndDuty) {
+		this.keyStaffProfessionalAndDuty = keyStaffProfessionalAndDuty;
+	}
+	
+	public String getServiceDesc() {
+		return serviceDesc;
+	}
+	
+	public void setServiceDesc(String serviceDesc) {
+		this.serviceDesc = serviceDesc;
+	}
+	
+	public String getExecutionDate() {
+		return executionDate;
+	}
+	
+	public void setExecutionDate(String executionDate) {
+		this.executionDate = executionDate;
+	}
+	
+	public String getProjectScaleAndType() {
+		return projectScaleAndType;
+	}
+	
+	public void setProjectScaleAndType(String projectScaleAndType) {
+		this.projectScaleAndType = projectScaleAndType;
+	}
+	
+	public String getDesignStage() {
+		return designStage;
+	}
+	
+	public void setDesignStage(String designStage) {
+		this.designStage = designStage;
+	}
+	
+	public String getDesignRange() {
+		return designRange;
+	}
+	
+	public void setDesignRange(String designRange) {
+		this.designRange = designRange;
+	}
+	
+	public String getCooperationWay() {
+		return cooperationWay;
+	}
+	
+	public void setCooperationWay(String cooperationWay) {
+		this.cooperationWay = cooperationWay;
+	}
+	
+	public String getContractExecuteCondition() {
+		return contractExecuteCondition;
+	}
+	
+	public void setContractExecuteCondition(String contractExecuteCondition) {
+		this.contractExecuteCondition = contractExecuteCondition;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/ProfitlossSheet.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ProfitlossSheet.java
new file mode 100644
index 0000000000000000000000000000000000000000..bef3045f2e363af6de1b3a6a1b55aa30b7acecc3
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ProfitlossSheet.java
@@ -0,0 +1,132 @@
+package com.gx.obe.struct.beans;
+
+import java.math.BigDecimal;
+
+/**
+ * @Description: 损益表
+ * @author chenxw
+ */
+public class ProfitlossSheet {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 财务ID
+	 */
+	private String financeId;
+	/**
+	 * 主营业务收入净额
+	 */
+	private BigDecimal mainIncome;
+	/**
+	 * 主营业务成本
+	 */
+	private BigDecimal mainCost;
+	/**
+	 * 财务费用
+	 */
+	private BigDecimal financialCost;
+	/**
+	 * 其他成本费用
+	 */
+	private BigDecimal otherCosts;
+	/**
+	 * 其中:技术开发、转让费用
+	 */
+	private BigDecimal developmentAndTransferCosts;
+	/**
+	 * 利润总额
+	 */
+	private BigDecimal profitLossprofit;
+	/**
+	 * 净利润
+	 */
+	private BigDecimal profitRetainedProfits;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getFinanceId() {
+		return financeId;
+	}
+	
+	public void setFinanceId(String financeId) {
+		this.financeId = financeId;
+	}
+	
+	public BigDecimal getMainIncome() {
+		return mainIncome;
+	}
+	
+	public void setMainIncome(BigDecimal mainIncome) {
+		this.mainIncome = mainIncome;
+	}
+	
+	public BigDecimal getMainCost() {
+		return mainCost;
+	}
+	
+	public void setMainCost(BigDecimal mainCost) {
+		this.mainCost = mainCost;
+	}
+	
+	public BigDecimal getFinancialCost() {
+		return financialCost;
+	}
+	
+	public void setFinancialCost(BigDecimal financialCost) {
+		this.financialCost = financialCost;
+	}
+	
+	public BigDecimal getOtherCosts() {
+		return otherCosts;
+	}
+	
+	public void setOtherCosts(BigDecimal otherCosts) {
+		this.otherCosts = otherCosts;
+	}
+	
+	public BigDecimal getDevelopmentAndTransferCosts() {
+		return developmentAndTransferCosts;
+	}
+	
+	public void setDevelopmentAndTransferCosts(BigDecimal developmentAndTransferCosts) {
+		this.developmentAndTransferCosts = developmentAndTransferCosts;
+	}
+	
+	public BigDecimal getProfitLossprofit() {
+		return profitLossprofit;
+	}
+	
+	public void setProfitLossprofit(BigDecimal profitLossprofit) {
+		this.profitLossprofit = profitLossprofit;
+	}
+	
+	public BigDecimal getProfitRetainedProfits() {
+		return profitRetainedProfits;
+	}
+	
+	public void setProfitRetainedProfits(BigDecimal profitRetainedProfits) {
+		this.profitRetainedProfits = profitRetainedProfits;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/ProjectLeader.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ProjectLeader.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c02d4b1796c03bf1f7ef6a30a671752d2c2e90d
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ProjectLeader.java
@@ -0,0 +1,216 @@
+package com.gx.obe.struct.beans;
+
+import java.util.List;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class ProjectLeader {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 模型数据ID
+	 */
+	private String modelDataId;
+	/**
+	 * 公司名称
+	 */
+	private String companyName;
+	/**
+	 * 姓名
+	 */
+	private String leaderName;
+	/**
+	 * 身份证号
+	 */
+	private String idnumber;
+	/**
+	 * 年龄
+	 */
+	private String age;
+	/**
+	 * 职务名称
+	 */
+	private String jobTitle;
+	/**
+	 * 工作经验(年)
+	 */
+	private String workExperience;
+	/**
+	 * 当前专业工作年限
+	 */
+	private String currentMajorExperience;
+	/**
+	 * 毕业学校
+	 */
+	private String graduateSchool;
+	/**
+	 * 毕业专业
+	 */
+	private String graduateMajor;
+	/**
+	 * 学历
+	 */
+	private String education;
+	/**
+	 * 职称
+	 */
+	private String professionalTitle;
+	/**
+	 * 是否为项目负责人
+	 */
+	private String isLeaderFlag;
+	/**
+	 * 证书列表
+	 */
+	private List<Certificate> certificateList;
+	/**
+	 * 工作经历
+	 */
+	private List<WorkExperience> workExperienceList;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getModelDataId() {
+		return modelDataId;
+	}
+	
+	public void setModelDataId(String modelDataId) {
+		this.modelDataId = modelDataId;
+	}
+	
+	public String getLeaderName() {
+		return leaderName;
+	}
+	
+	public void setLeaderName(String leaderName) {
+		this.leaderName = leaderName;
+	}
+	
+	public String getIdnumber() {
+		return idnumber;
+	}
+	
+	public void setIdnumber(String idnumber) {
+		this.idnumber = idnumber;
+	}
+	
+	public String getAge() {
+		return age;
+	}
+	
+	public void setAge(String age) {
+		this.age = age;
+	}
+	
+	public String getJobTitle() {
+		return jobTitle;
+	}
+	
+	public void setJobTitle(String jobTitle) {
+		this.jobTitle = jobTitle;
+	}
+	
+	public String getWorkExperience() {
+		return workExperience;
+	}
+	
+	public void setWorkExperience(String workExperience) {
+		this.workExperience = workExperience;
+	}
+	
+	public List<Certificate> getCertificateList() {
+		return certificateList;
+	}
+	
+	public void setCertificateList(List<Certificate> certificateList) {
+		this.certificateList = certificateList;
+	}
+	
+	public String getCompanyName() {
+		return companyName;
+	}
+	
+	public void setCompanyName(String companyName) {
+		this.companyName = companyName;
+	}
+	
+	public String getCurrentMajorExperience() {
+		return currentMajorExperience;
+	}
+	
+	public void setCurrentMajorExperience(String currentMajorExperience) {
+		this.currentMajorExperience = currentMajorExperience;
+	}
+	
+	public String getGraduateSchool() {
+		return graduateSchool;
+	}
+	
+	public void setGraduateSchool(String graduateSchool) {
+		this.graduateSchool = graduateSchool;
+	}
+	
+	public String getGraduateMajor() {
+		return graduateMajor;
+	}
+	
+	public void setGraduateMajor(String graduateMajor) {
+		this.graduateMajor = graduateMajor;
+	}
+	
+	public String getEducation() {
+		return education;
+	}
+	
+	public void setEducation(String education) {
+		this.education = education;
+	}
+	
+	public List<WorkExperience> getWorkExperienceList() {
+		return workExperienceList;
+	}
+	
+	public void setWorkExperienceList(List<WorkExperience> workExperienceList) {
+		this.workExperienceList = workExperienceList;
+	}
+	
+	public String getProfessionalTitle() {
+		return professionalTitle;
+	}
+	
+	public void setProfessionalTitle(String professionalTitle) {
+		this.professionalTitle = professionalTitle;
+	}
+
+	public String getIsLeaderFlag() {
+		return isLeaderFlag;
+	}
+
+	public void setIsLeaderFlag(String isLeaderFlag) {
+		this.isLeaderFlag = isLeaderFlag;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/Qualification.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Qualification.java
new file mode 100644
index 0000000000000000000000000000000000000000..45d348442fcc1bd388752472a659725ec8cbedec
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/Qualification.java
@@ -0,0 +1,154 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class Qualification {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 模型数据ID
+	 */
+	private String modelDataId;
+	/**
+	 * 证书名称
+	 */
+	private String certificateName;
+	/**
+	 * 获奖工程名称
+	 */
+	private String awardProjectName;
+	/**
+	 * 单位名称
+	 */
+	private String companyName;
+	/**
+	 * 证书等级
+	 */
+	private String awardLevel;
+	/**
+	 * 证书编号
+	 */
+	private String certificateNumber;
+	/**
+	 * 发证机关(认证单位)
+	 */
+	private String issueAuthority;
+	/**
+	 * 发证日期
+	 */
+	private String issueDate;
+	/**
+	 * 有效期至
+	 */
+	private String periodValidity;
+	/**
+	 * 获奖工程名称
+	 */
+	private String projectName;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getModelDataId() {
+		return modelDataId;
+	}
+	
+	public void setModelDataId(String modelDataId) {
+		this.modelDataId = modelDataId;
+	}
+	
+	public String getCertificateName() {
+		return certificateName;
+	}
+	
+	public void setCertificateName(String certificateName) {
+		this.certificateName = certificateName;
+	}
+	
+	public String getAwardProjectName() {
+		return awardProjectName;
+	}
+	
+	public void setAwardProjectName(String awardProjectName) {
+		this.awardProjectName = awardProjectName;
+	}
+	
+	public String getCompanyName() {
+		return companyName;
+	}
+	
+	public void setCompanyName(String companyName) {
+		this.companyName = companyName;
+	}
+	
+	public String getAwardLevel() {
+		return awardLevel;
+	}
+	
+	public void setAwardLevel(String awardLevel) {
+		this.awardLevel = awardLevel;
+	}
+	
+	public String getCertificateNumber() {
+		return certificateNumber;
+	}
+	
+	public void setCertificateNumber(String certificateNumber) {
+		this.certificateNumber = certificateNumber;
+	}
+	
+	public String getIssueAuthority() {
+		return issueAuthority;
+	}
+	
+	public void setIssueAuthority(String issueAuthority) {
+		this.issueAuthority = issueAuthority;
+	}
+	
+	public String getIssueDate() {
+		return issueDate;
+	}
+	
+	public void setIssueDate(String issueDate) {
+		this.issueDate = issueDate;
+	}
+	
+	public String getPeriodValidity() {
+		return periodValidity;
+	}
+	
+	public void setPeriodValidity(String periodValidity) {
+		this.periodValidity = periodValidity;
+	}
+	
+	public String getProjectName() {
+		return projectName;
+	}
+	
+	public void setProjectName(String projectName) {
+		this.projectName = projectName;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/RespItemDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/RespItemDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac07b5d23b8baabb4e7ea4760c6b5207d9577e00
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/RespItemDO.java
@@ -0,0 +1,82 @@
+package com.gx.obe.struct.beans;
+/**
+ * 标书定位
+ * @author dell
+ *
+ */
+public class RespItemDO {
+
+//	<RespItem evalFactorId="630d6016d5234dbea9d311e0446b2298" fileId="55961ba60deba50831be7cc254b09201" fileName="商务部分--测试.pdf">
+//	  <id>23a81f9448314bc99127036432262165</id>
+//	  <pageNumber>1</pageNumber>
+//	  <endPageNumber>3</endPageNumber>
+//	  <name>(1-3)商务部分--测试</name>
+//	  <isNewRespItemInEditor>false</isNewRespItemInEditor>
+//	  <IsUserBindInFactor>true</IsUserBindInFactor>
+//	 </RespItem>
+	
+	private String evalFactorId;
+	
+	private String fileId;
+	
+	private String fileName;
+	
+	private String pageNumber;
+	
+	private String endPageNumber;
+	
+	private String name;
+	
+	public String getPage() {
+		return "【P" + pageNumber + "-" + endPageNumber + "页】";
+	}
+
+	public String getEvalFactorId() {
+		return evalFactorId;
+	}
+
+	public void setEvalFactorId(String evalFactorId) {
+		this.evalFactorId = evalFactorId;
+	}
+
+	public String getFileId() {
+		return fileId;
+	}
+
+	public void setFileId(String fileId) {
+		this.fileId = fileId;
+	}
+
+	public String getFileName() {
+		return fileName;
+	}
+
+	public void setFileName(String fileName) {
+		this.fileName = fileName;
+	}
+
+	public String getPageNumber() {
+		return pageNumber;
+	}
+
+	public void setPageNumber(String pageNumber) {
+		this.pageNumber = pageNumber;
+	}
+
+	public String getEndPageNumber() {
+		return endPageNumber;
+	}
+
+	public void setEndPageNumber(String endPageNumber) {
+		this.endPageNumber = endPageNumber;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/ScoreOptionsDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ScoreOptionsDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..10d4cf85cb155175b3facc44261c0dff514eab68
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/ScoreOptionsDO.java
@@ -0,0 +1,35 @@
+package com.gx.obe.struct.beans;
+
+public class ScoreOptionsDO {
+	/**
+	 * @Description: 评审得分项id
+	 */
+	private String scoreItemId;
+	/**
+	 * @Description: 评审项名称
+	 */
+	private String name;
+	/**
+	 * @Description: 得分
+	 */
+	private String score;
+	public String getScoreItemId() {
+		return scoreItemId;
+	}
+	public void setScoreItemId(String scoreItemId) {
+		this.scoreItemId = scoreItemId;
+	}
+	public String getName() {
+		return name;
+	}
+	public void setName(String name) {
+		this.name = name;
+	}
+	public String getScore() {
+		return score;
+	}
+	public void setScore(String score) {
+		this.score = score;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/SelfEvalParamsDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/SelfEvalParamsDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..58d690dab3572712836e355c92d33fb3442d9327
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/SelfEvalParamsDO.java
@@ -0,0 +1,69 @@
+package com.gx.obe.struct.beans;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.gx.obe.http.json.JsonUtil;
+
+/**
+ * 供应商自我评结构化响应内容
+ * @author gnauh
+ *
+ */
+public class SelfEvalParamsDO {
+	
+//	<paramValueList>
+//	   <paramValue>
+//	    <dataType><![CDATA[string]]></dataType>
+//	    <dataValue><![CDATA[4bbd0336c9624562a6b3639d92824ff5]]></dataValue>
+//	   </paramValue>
+//	  </paramValueList>
+	  
+	/**
+	 * 下拉选项内容
+	 */
+	private List<ParamValueDO> paramValueList;
+	
+	public String toJson() {
+		return JsonUtil.jsonObjectToStr(this);
+	}
+
+	public List<ParamValueDO> getParamValueList() {
+		return paramValueList;
+	}
+
+	public void setParamValueList(List<ParamValueDO> paramValueList) {
+		this.paramValueList = paramValueList;
+	}
+	
+	public void clearParamValue() {
+		if(null != paramValueList) {
+			paramValueList.clear();
+		}
+	}
+	public void addParamValue(ParamValueDO paramValueDO) {
+		if(null == paramValueList) {
+			paramValueList = new ArrayList<ParamValueDO>();
+		}
+		paramValueList.add(paramValueDO);
+	}
+	
+	/**
+	 * 获取选项值
+	 */
+	public String getSelectParamValue() {
+		if(null != paramValueList && paramValueList.size() > 0) {
+			return paramValueList.get(paramValueList.size() -1).getDataValue();
+		}
+		return null;
+	}
+	/**
+	 * 获取选项值
+	 */
+	public void setSelectParamValue(String dataValue) {
+		if(null != paramValueList && paramValueList.size() > 0) {
+			paramValueList.get(paramValueList.size() -1).setDataValue(dataValue);;
+		}
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/StructDateInfo.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/StructDateInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..2f5770e5d69e650062870ec3b90e58f27a967044
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/StructDateInfo.java
@@ -0,0 +1,59 @@
+package com.gx.obe.struct.beans;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+public class StructDateInfo {
+	
+	private final List<TemplateDataItem> templateDataItemList = new CopyOnWriteArrayList<>();
+	private final List<TemplateTable> templateTableList = new CopyOnWriteArrayList<>();
+	private final List<ModelData> modelDataList = new CopyOnWriteArrayList<>();
+	private final List<BusinessLicense> businessLicenseList = new CopyOnWriteArrayList<>();
+	private final List<Finance> financeList = new CopyOnWriteArrayList<>();
+	private final List<Performance> performanceList = new CopyOnWriteArrayList<>();
+	private final List<BidderBasicInfo> bidderBasicInfoList = new CopyOnWriteArrayList<>();
+	private final List<Qualification> qualificationList = new CopyOnWriteArrayList<>();
+	private final List<ProjectLeader> projectLeaderList = new CopyOnWriteArrayList<>();
+	private final List<AttachmentFile> attachmentFileList = new CopyOnWriteArrayList<>();
+	
+	public List<TemplateTable> getTemplateTableList() {
+		return templateTableList;
+	}
+	
+	public List<ModelData> getModelDataList() {
+		return modelDataList;
+	}
+	
+	public List<BusinessLicense> getBusinessLicenseList() {
+		return businessLicenseList;
+	}
+	
+	public List<Finance> getFinanceList() {
+		return financeList;
+	}
+	
+	public List<Performance> getPerformanceList() {
+		return performanceList;
+	}
+	
+	public List<BidderBasicInfo> getBidderBasicInfoList() {
+		return bidderBasicInfoList;
+	}
+	
+	public List<Qualification> getQualificationList() {
+		return qualificationList;
+	}
+	
+	public List<ProjectLeader> getProjectLeaderList() {
+		return projectLeaderList;
+	}
+	
+	public List<TemplateDataItem> getTemplateDataItemList() {
+		return templateDataItemList;
+	}
+	
+	public List<AttachmentFile> getAttachmentFileList() {
+		return attachmentFileList;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/TemplateDataItem.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/TemplateDataItem.java
new file mode 100644
index 0000000000000000000000000000000000000000..c72117ec48a289b5c90052e4fa7ada5f337fc285
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/TemplateDataItem.java
@@ -0,0 +1,100 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * @author mazc
+ * @Description:
+ */
+public class TemplateDataItem {
+	
+	private String id;
+	private String tenderId;
+	private String supplierId;
+	private String relChapterType;
+	private String dataCode;
+	private String name;
+	private String value;
+	private String type;
+	private String dataType;
+	private String unit;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getSupplierId() {
+		return supplierId;
+	}
+	
+	public void setSupplierId(String supplierId) {
+		this.supplierId = supplierId;
+	}
+	
+	public String getRelChapterType() {
+		return relChapterType;
+	}
+	
+	public void setRelChapterType(String relChapterType) {
+		this.relChapterType = relChapterType;
+	}
+	
+	public String getDataCode() {
+		return dataCode;
+	}
+	
+	public void setDataCode(String dataCode) {
+		this.dataCode = dataCode;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public String getValue() {
+		return value;
+	}
+	
+	public void setValue(String value) {
+		this.value = value;
+	}
+	
+	public String getType() {
+		return type;
+	}
+	
+	public void setType(String type) {
+		this.type = type;
+	}
+	
+	public String getDataType() {
+		return dataType;
+	}
+	
+	public void setDataType(String dataType) {
+		this.dataType = dataType;
+	}
+	
+	public String getUnit() {
+		return unit;
+	}
+	
+	public void setUnit(String unit) {
+		this.unit = unit;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/TemplateTable.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/TemplateTable.java
new file mode 100644
index 0000000000000000000000000000000000000000..f54b6e5266fda12f7a7ea1187af2bf8063b6d749
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/TemplateTable.java
@@ -0,0 +1,82 @@
+package com.gx.obe.struct.beans;
+
+/**
+ * @Description: 小范本表格
+ * @author chenxw
+ */
+public class TemplateTable {
+	
+	private String id;
+	private String tenderId;
+	private String supplierId;
+	private String relChapterType;
+	private String dataCode;
+	private String xmlPath;
+	private String tableName;
+	private String tableInfo;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getSupplierId() {
+		return supplierId;
+	}
+	
+	public void setSupplierId(String supplierId) {
+		this.supplierId = supplierId;
+	}
+	
+	public String getRelChapterType() {
+		return relChapterType;
+	}
+	
+	public void setRelChapterType(String relChapterType) {
+		this.relChapterType = relChapterType;
+	}
+	
+	public String getDataCode() {
+		return dataCode;
+	}
+	
+	public void setDataCode(String dataCode) {
+		this.dataCode = dataCode;
+	}
+	
+	public String getXmlPath() {
+		return xmlPath;
+	}
+	
+	public void setXmlPath(String xmlPath) {
+		this.xmlPath = xmlPath;
+	}
+	
+	public String getTableName() {
+		return tableName;
+	}
+	
+	public void setTableName(String tableName) {
+		this.tableName = tableName;
+	}
+	
+	public String getTableInfo() {
+		return tableInfo;
+	}
+	
+	public void setTableInfo(String tableInfo) {
+		this.tableInfo = tableInfo;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/TimeModelDO.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/TimeModelDO.java
new file mode 100644
index 0000000000000000000000000000000000000000..7f87242929caa355f0eb5933f4a2755cf7fe6690
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/TimeModelDO.java
@@ -0,0 +1,138 @@
+package com.gx.obe.struct.beans;
+
+public class TimeModelDO {
+	
+	/**
+	 * @Description: 基础分
+	 */
+	private String baseScore;
+	/**
+	 * @Description: 方式:方式1 01,方式2 02 方式1 会用到以下节点 方式2 只会用到交货日期,只能供应商响应是才出现
+	 */
+	private String mode;
+	/**
+	 * @Description: 日期:yyyy-MM-dd HH:mm
+	 */
+	private String deliveryDate;
+	/**
+	 * @Description: 天数1:可填
+	 */
+	private String dayFirst;
+	/**
+	 * @Description: 类型1:扣分01
+	 */
+	private String dealTypeFirst;
+	/**
+	 * @Description: 分值1
+	 */
+	private String dealScoreFirst;
+	/**
+	 * @Description: 天数2:可填
+	 */
+	private String daySecond;
+	/**
+	 * @Description: 类型2:扣分01
+	 */
+	private String dealTypeSecond;
+	/**
+	 * @Description: 分值2
+	 */
+	private String dealScoreSecond;
+	/**
+	 * @Description: 是否项:是 01,否 00
+	 */
+	private String option;
+	/**
+	 * @Description: 备注:可填
+	 */
+	private String memo;
+	
+	public String getBaseScore() {
+		return baseScore;
+	}
+	
+	public void setBaseScore(String baseScore) {
+		this.baseScore = baseScore;
+	}
+	
+	public String getMode() {
+		return mode;
+	}
+	
+	public void setMode(String mode) {
+		this.mode = mode;
+	}
+	
+	public String getDeliveryDate() {
+		return deliveryDate;
+	}
+	
+	public void setDeliveryDate(String deliveryDate) {
+		this.deliveryDate = deliveryDate;
+	}
+	
+	public String getDayFirst() {
+		return dayFirst;
+	}
+	
+	public void setDayFirst(String dayFirst) {
+		this.dayFirst = dayFirst;
+	}
+	
+	public String getDealTypeFirst() {
+		return dealTypeFirst;
+	}
+	
+	public void setDealTypeFirst(String dealTypeFirst) {
+		this.dealTypeFirst = dealTypeFirst;
+	}
+	
+	public String getDealScoreFirst() {
+		return dealScoreFirst;
+	}
+	
+	public void setDealScoreFirst(String dealScoreFirst) {
+		this.dealScoreFirst = dealScoreFirst;
+	}
+	
+	public String getDaySecond() {
+		return daySecond;
+	}
+	
+	public void setDaySecond(String daySecond) {
+		this.daySecond = daySecond;
+	}
+	
+	public String getDealTypeSecond() {
+		return dealTypeSecond;
+	}
+	
+	public void setDealTypeSecond(String dealTypeSecond) {
+		this.dealTypeSecond = dealTypeSecond;
+	}
+	
+	public String getDealScoreSecond() {
+		return dealScoreSecond;
+	}
+	
+	public void setDealScoreSecond(String dealScoreSecond) {
+		this.dealScoreSecond = dealScoreSecond;
+	}
+	
+	public String getOption() {
+		return option;
+	}
+	
+	public void setOption(String option) {
+		this.option = option;
+	}
+	
+	public String getMemo() {
+		return memo;
+	}
+	
+	public void setMemo(String memo) {
+		this.memo = memo;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/beans/WorkExperience.java b/com.gx.obe.struct/src/com/gx/obe/struct/beans/WorkExperience.java
new file mode 100644
index 0000000000000000000000000000000000000000..c124ea483c00e8a04f51a0a58858056de8ca0134
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/beans/WorkExperience.java
@@ -0,0 +1,126 @@
+package com.gx.obe.struct.beans;
+
+public class WorkExperience {
+	
+	/**
+	 * 主键
+	 */
+	private String id;
+	/**
+	 * 项目ID
+	 */
+	private String tenderId;
+	/**
+	 * 项目负责人ID
+	 */
+	private String projectLeaderId;
+	/**
+	 * æ—¶é—´
+	 */
+	private String time;
+	/**
+	 * 参加的类似项目
+	 */
+	private String projectName;
+	/**
+	 * 担任职务
+	 */
+	private String jobTitle;
+	/**
+	 * 发包人及其联系联系电话
+	 */
+	private String contractInfo;
+	/**
+	 * 承担的工作
+	 */
+	private String bearWork;
+	/**
+	 * 容量(MW)
+	 */
+	private String capacity;
+	/**
+	 * 排序
+	 */
+	private int sortNo;
+	
+	public String getId() {
+		return id;
+	}
+	
+	public void setId(String id) {
+		this.id = id;
+	}
+	
+	public String getTenderId() {
+		return tenderId;
+	}
+	
+	public void setTenderId(String tenderId) {
+		this.tenderId = tenderId;
+	}
+	
+	public String getProjectLeaderId() {
+		return projectLeaderId;
+	}
+	
+	public void setProjectLeaderId(String projectLeaderId) {
+		this.projectLeaderId = projectLeaderId;
+	}
+	
+	public String getTime() {
+		return time;
+	}
+	
+	public void setTime(String time) {
+		this.time = time;
+	}
+	
+	public String getProjectName() {
+		return projectName;
+	}
+	
+	public void setProjectName(String projectName) {
+		this.projectName = projectName;
+	}
+	
+	public String getJobTitle() {
+		return jobTitle;
+	}
+	
+	public void setJobTitle(String jobTitle) {
+		this.jobTitle = jobTitle;
+	}
+	
+	public String getContractInfo() {
+		return contractInfo;
+	}
+	
+	public void setContractInfo(String contractInfo) {
+		this.contractInfo = contractInfo;
+	}
+	
+	public int getSortNo() {
+		return sortNo;
+	}
+	
+	public void setSortNo(int sortNo) {
+		this.sortNo = sortNo;
+	}
+	
+	public String getBearWork() {
+		return bearWork;
+	}
+	
+	public void setBearWork(String bearWork) {
+		this.bearWork = bearWork;
+	}
+	
+	public String getCapacity() {
+		return capacity;
+	}
+	
+	public void setCapacity(String capacity) {
+		this.capacity = capacity;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/AttachmentComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/AttachmentComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..5458d754782a00fbf87adc6a27d024e227a7c208
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/AttachmentComposite.java
@@ -0,0 +1,55 @@
+package com.gx.obe.struct.composite;
+
+import java.io.File;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.component.utils.CompositeUtils;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.struct.beans.AttachmentFile;
+import com.gx.obe.struct.service.AttachmentFileService;
+
+public class AttachmentComposite extends Composite {
+	
+	private final AttachmentFileService attachmentFileService = new AttachmentFileService();
+	
+	private final Prop<List<AttachmentFile>> attachmentFileList = new Prop<>();
+	
+	private final String tenderId;
+	
+	private String bidFilePath;
+	
+	public AttachmentComposite(Composite parent, String tenderId) {
+		super(parent, SWT.NONE);
+		this.tenderId = tenderId;
+		
+		RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
+		rowLayout.marginRight = 5;
+		rowLayout.marginLeft = 5;
+		rowLayout.marginBottom = 5;
+		rowLayout.marginTop = 5;
+		rowLayout.spacing = 5;
+		setLayout(rowLayout);
+		
+		attachmentFileList.bind(l -> {
+			CompositeUtils.disposeChildren(this);
+			l.forEach(t -> new FileButton(this, new File(bidFilePath + t.getFileUrl()), t.getFileName()));
+			this.layout();
+		});
+		
+	}
+	
+	public void refresh(String supplierId, String businessId) {
+		bidFilePath = Constants.getBidFilePath(tenderId, supplierId);
+		RxSwt.run(() -> attachmentFileService.getAttachmentFileList(businessId)).checkWidget(this).exe(attachmentFileList::set);
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/ClearBidReviewEntryComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/ClearBidReviewEntryComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..ac4b4eaccfc3c05cd560492347f94f928da30e27
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/ClearBidReviewEntryComposite.java
@@ -0,0 +1,319 @@
+package com.gx.obe.struct.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.core.widgets.ELink;
+import org.eclipse.swt.core.widgets.ESepator;
+import org.eclipse.swt.core.widgets.ImageButton;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.common.icons.IconsActivator;
+import com.gx.obe.common.widget.button.EvaluationButton;
+
+import com.gx.obe.message.Messages;
+import com.gx.obe.struct.EvalFactorText;
+import com.gx.obe.struct.dialog.EditOpinionShell;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.struct.listener.EditOpinionListener;
+import com.gx.obe.struct.listener.ReturnListener;
+import com.gx.obe.util.utils.ObjectUtils;
+import com.gx.obe.util.utils.StringUtils;
+import com.gx.obe.util.utils.UuidUtils;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+import com.swtdesigner.ResourceManager;
+import com.swtdesigner.SWTResourceManager;
+
+public class ClearBidReviewEntryComposite extends Composite {
+	
+	private final SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	
+	private final Prop<EvaluationFactor> evaluationFactorProp = new Prop<>();
+	
+	private final Prop<EvaluationContentData> evaluationContentData = new Prop<>();
+	private final List<ReturnListener> returnListenerList = new ArrayList<>();
+	
+	private class EvaluationContentData {
+		private String supplierId;
+		private String factorCode;
+		private EvaluationFactorTypeEnum factorTypeEnum;
+	}
+	private EvaluationFactor curFactor;
+	private SupplierEvaluationFactor supplierEvaluationFactor;
+	private Composite factorOpinionComposite;
+	private Text opinionText;
+	private Text supplierOpinionText;
+	private ImageButton opinionBtn;
+
+	private ImageButton supplierOpinionBtn;
+
+	private EvaluationButton saveBtn;
+
+	private Label wordCountLabel;
+
+	private ELink editOpinionLink;
+
+	private EvaluationButton backBtn;
+	
+	public ClearBidReviewEntryComposite(Composite parent, String tenderId) {
+		super(parent, SWT.NONE);
+		
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		GridLayout gridLayout = new GridLayout(3, false);
+		gridLayout.horizontalSpacing = 0;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		EvaluationContentComposite composite = new EvaluationContentComposite(this, tenderId);
+		GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_composite.widthHint = 600;
+		composite.setLayoutData(gd_composite);
+		evaluationContentData.bind(t -> composite.refresh(t.supplierId, t.factorCode, t.factorTypeEnum));
+		
+		ESepator label = new ESepator(this, SWT.VERTICAL);
+		label.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, true, 1, 1));
+		label.setBackground(ColorConstants.BORDER_LINE_COLOR);
+		
+		Composite composite_1 = new Composite(this, SWT.NONE);
+		composite_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_LIGHT_SHADOW));
+		GridLayout gl_composite_1 = new GridLayout(1, false);
+		gl_composite_1.verticalSpacing = 1;
+		gl_composite_1.marginHeight = 0;
+		gl_composite_1.marginWidth = 0;
+		composite_1.setLayout(gl_composite_1);
+		GridData gd_composite_1 = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_composite_1.widthHint = 400;
+		composite_1.setLayoutData(gd_composite_1);
+		
+		Composite composite_2 = new Composite(composite_1, SWT.NONE);
+		composite_2.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		composite_2.setLayout(new GridLayout(1, false));
+		GridData gd_composite_2 = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_composite_2.heightHint = 260;
+		composite_2.setLayoutData(gd_composite_2);
+		
+		EvalFactorText text = new EvalFactorText(composite_2);
+		text.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		evaluationFactorProp.bind(text::refresh);
+		
+		Composite selfOpinionComposite = new Composite(composite_1, SWT.NONE);
+		selfOpinionComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
+		GridLayout gl_selfOpinion = new GridLayout(1, false);
+		gl_selfOpinion.marginWidth = 0;
+		gl_selfOpinion.marginHeight = 0;
+		selfOpinionComposite.setLayout(gl_selfOpinion);
+		selfOpinionComposite.setBackground(SWTResourceManager.getColor(240, 240, 240));
+		selfOpinionComposite.setBackgroundMode(SWT.INHERIT_FORCE);
+		
+		supplierOpinionBtn = new ImageButton(selfOpinionComposite, SWT.NONE);
+		supplierOpinionBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		supplierOpinionBtn.setLeftMargin(20);
+		supplierOpinionBtn.setRightMargin(20);
+		supplierOpinionBtn.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
+		supplierOpinionBtn.setText(Messages.BidFileSelfComment);
+		setanswerBtnCss(supplierOpinionBtn);
+		
+		Composite selfOpinionTextComposite = new Composite(composite_1, SWT.NONE);
+		selfOpinionTextComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		selfOpinionTextComposite.setBackgroundMode(SWT.INHERIT_FORCE);
+		GridData gd_selfOpinionTextComposite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_selfOpinionTextComposite.heightHint = 150;
+		selfOpinionTextComposite.setLayoutData(gd_selfOpinionTextComposite);
+		selfOpinionTextComposite.setLayout(new GridLayout(1, false));
+		
+		supplierOpinionText = new Text(selfOpinionTextComposite, SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL);
+		supplierOpinionText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		supplierOpinionText.setEditable(false);
+		
+		Composite opinionComposite = new Composite(composite_1, SWT.NONE);
+		opinionComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
+		GridLayout gl_opinion = new GridLayout(1, false);
+		gl_opinion.marginWidth = 0;
+		gl_opinion.marginHeight = 0;
+		opinionComposite.setLayout(gl_opinion);
+		opinionComposite.setBackground(SWTResourceManager.getColor(240, 240, 240));
+		opinionComposite.setBackgroundMode(SWT.INHERIT_FORCE);
+		
+		opinionBtn = new ImageButton(opinionComposite, SWT.NONE);
+		opinionBtn.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		opinionBtn.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
+		opinionBtn.setText(Messages.BidFileComments);
+		setanswerBtnCss(opinionBtn);
+		
+		factorOpinionComposite = new Composite(composite_1, SWT.NONE);
+		factorOpinionComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		factorOpinionComposite.setBackgroundMode(SWT.INHERIT_FORCE);
+		GridLayout gl_factorOpinionComposite = new GridLayout(2, false);
+		gl_factorOpinionComposite.marginHeight = 0;
+		gl_factorOpinionComposite.marginWidth = 0;
+		factorOpinionComposite.setLayout(gl_factorOpinionComposite);
+		GridData gd_factorOpinionComposite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_factorOpinionComposite.heightHint = 180;
+		factorOpinionComposite.setLayoutData(gd_factorOpinionComposite);;
+		
+		opinionText = new Text(factorOpinionComposite, SWT.WRAP | SWT.V_SCROLL);
+		opinionText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));;
+		opinionText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent arg0) {
+				wordCountLabel.setText(opinionText.getText().length() +"/2000");
+			}
+		});
+		opinionText.setTextLimit(2000);
+		opinionText.setEditable(false);
+		
+		wordCountLabel = new Label(factorOpinionComposite, SWT.NONE);
+		wordCountLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));;
+		wordCountLabel.setText("0/2000");
+		
+		editOpinionLink = new ELink(factorOpinionComposite, SWT.NONE);
+		editOpinionLink.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));;
+		editOpinionLink.setText("修改");
+		editOpinionLink.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/edit.png"));
+		editOpinionLink.addMouseListener(new MouseAdapter() {
+			public void mouseUp(MouseEvent e) {
+				editOpinionAction();
+			}
+		});
+		
+		Composite buttonComposite = new Composite(composite_1, SWT.NONE);
+		buttonComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		buttonComposite.setLayout(new GridLayout(2, false));
+		buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		saveBtn = new EvaluationButton(buttonComposite, SWT.NONE);
+		saveBtn.addMouseListener(MouseListener.mouseUpAdapter($ -> saveAction()));
+		saveBtn.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
+		saveBtn.setText("保存");
+		
+		backBtn = new EvaluationButton(buttonComposite, SWT.NONE);
+		backBtn.addMouseListener(MouseListener.mouseUpAdapter($ -> returnAction()));
+		backBtn.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 1, 1));
+		backBtn.setText("返回");
+	}
+	
+	public void refresh(EvaluationFactor evaluationFactor, SupplierEvaluationFactor supplierEvaluationFactor, EvaluationFactorTypeEnum factorTypeEnum) {
+		this.supplierEvaluationFactor = supplierEvaluationFactor;
+		this.evaluationFactorProp.set(evaluationFactor);
+		this.curFactor = evaluationFactor;
+		EvaluationContentData data = new EvaluationContentData();
+		data.supplierId = supplierEvaluationFactor.getSupplierId();
+		data.factorCode = supplierEvaluationFactor.getFactorCode();
+		data.factorTypeEnum = factorTypeEnum;
+		this.evaluationContentData.set(data);
+		saveBtn.setEnabled(false);
+		opinionText.setText(ObjectUtils.getObjString(supplierEvaluationFactor.getOpinion()));
+		opinionText.setToolTipText(supplierEvaluationFactor.getModifyReason());
+		supplierOpinionText.setText(ObjectUtils.getObjString(supplierEvaluationFactor.getFactorResponse()));
+	}
+	
+	  /**
+     * @Description: 设置指标分类的按钮
+     * @author wangxiang
+     * @param imageBtn
+     */
+    private void setanswerBtnCss(ImageButton imageBtn) {
+        imageBtn.setRightMargin(10);
+        imageBtn.setLeftMargin(10);
+        imageBtn.setTopMargin(5);
+        imageBtn.setBottomMargin(5);
+        imageBtn.setRightMargin(20);
+        imageBtn.setLeftMargin(20);
+        imageBtn.setTopMargin(5);
+        imageBtn.setBottomMargin(5);
+        imageBtn.setRightMargin(10);
+        imageBtn.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
+        imageBtn.setForeground(ColorConstants.SKIN_SELECTOIN_FOREGROUND);
+        imageBtn.setBackgroundColor(ColorConstants.SKIN_BG);
+
+    }
+    
+	public void addReturnListener(ReturnListener returnListener) {
+		this.returnListenerList.add(returnListener);
+	}
+	
+	  /**
+     * 修改评审意见
+     */
+    private void editOpinionAction() {
+    	
+    	if (null != supplierEvaluationFactor) {
+    		opinionText.setText(ObjectUtils.getObjString(supplierEvaluationFactor.getOpinion()));
+    		final boolean saveBtnIsEnabled = saveBtn.getEnabled();
+    		saveBtn.setEnabled(false);
+    		EditOpinionShell editOpinionShell = new EditOpinionShell(getShell(), curFactor, supplierEvaluationFactor, new EditOpinionListener() {
+    			@Override
+    			public void editOpinion(String opinion, String modifyReason) {
+    				saveBtn.setEnabled(true);
+    				opinionText.setText(ObjectUtils.getObjString(opinion));
+    				opinionText.setToolTipText(modifyReason);
+    				supplierEvaluationFactor.setModifyReason(modifyReason);
+    			}
+				@Override
+				public void cancle() {
+					saveBtn.setEnabled(saveBtnIsEnabled);
+				}
+    		});
+    		if (null != editOpinionShell && !editOpinionShell.isDisposed()) {
+    			// 设置界面位置
+    			editOpinionShell.setLocation(factorOpinionComposite.toDisplay(0, 0));
+    			Rectangle rectangle = factorOpinionComposite.getBounds();
+    			// 设置界面大小
+    			editOpinionShell.setSize(rectangle.width, rectangle.height);
+    			editOpinionShell.open();
+    		}
+    	}
+    }
+	
+	private void saveAction() {
+		if(!saveBtn.getEnabled())return;
+		if(opinionText.getText().trim().length() == 0) {
+			MessageDialog.openShortMessage("评议意见不能为空!");
+			return;
+		}
+		saveBtn.setEnabled(false);
+		backBtn.setEnabled(false);
+		supplierEvaluationFactor.setOpinion(opinionText.getText());
+		boolean saveFlag = false;
+		if (StringUtils.isEmpty(supplierEvaluationFactor.getId())) {
+            supplierEvaluationFactor.setId(UuidUtils.getUUID());
+            saveFlag = supplierEvaluationFactorService.insert(supplierEvaluationFactor);
+        } else {
+        	// TODO 这里需要保存修改原因
+        	saveFlag = supplierEvaluationFactorService.updateAssignProperty(supplierEvaluationFactor, new String[] { "opinion", "factorResponse","modifyReason" ,"paramValues"});
+//        	saveFlag = supplierEvaluationFactorService.updateAssignProperty(supplierEvaluationFactor, new String[] { "opinion", "factorResponse" ,"paramValues"});
+        }
+		if(saveFlag) {
+			MessageDialog.openShortMessage("保存成功!");
+			
+		}else {
+			MessageDialog.openWarning(getShell(), "保存失败!");
+			saveBtn.setEnabled(true);
+		}
+		backBtn.setEnabled(true);
+	}
+	
+	private void returnAction() {
+		returnListenerList.forEach(l -> l.returnAction());
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/EvaluationContentComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/EvaluationContentComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..796ff0fde52eb61fa032f2c330e63f2c391b94b4
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/EvaluationContentComposite.java
@@ -0,0 +1,242 @@
+package com.gx.obe.struct.composite;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.widgets.ELink;
+import org.eclipse.swt.core.widgets.ESepator;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.common.widget.button.RectangleRadioButton;
+import com.gx.obe.component.handler.TabHandler;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.struct.Global;
+import com.gx.obe.struct.PdfFileView;
+import com.gx.obe.struct.beans.ModelData;
+import com.gx.obe.struct.enums.DataCategoryEnum;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.struct.enums.ModelDataTypeEnum;
+import com.gx.obe.struct.handler.RelChapterTypeHandler;
+import com.gx.obe.struct.parse.BidFileIndexTreeXmlParse;
+import com.gx.obe.struct.service.EvaluationContentService;
+import com.gx.obe.struct.service.ModelDataService;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.web.entity.evaluation.EvaluationContent;
+import com.swtdesigner.SWTResourceManager;
+
+public class EvaluationContentComposite extends Composite {
+	
+	private final EvaluationContentService evaluationContentService = new EvaluationContentService();
+	private final ModelDataService modelDataService = new ModelDataService();
+	
+	private final String tenderId;
+	
+	private final Prop<EvaluationContentData> evaluationContentData = new Prop<>();
+	private final Prop<PdfFileData> pdfFileData = new Prop<>();
+	private final Prop<String> tips = new Prop<>();
+	
+	private final Prop<Boolean> showFile = new Prop<>();
+	private final Prop<Boolean> showSwitch = new Prop<>(false);
+	
+	private class RootNodeChapterData {
+		private String name;
+		private String type;
+	}
+	
+	private class EvaluationContentData {
+		private String supplierId;
+		private EvaluationFactorTypeEnum factorTypeEnum;
+		private List<EvaluationContent> evaluationContentList;
+	}
+	
+	private class PdfFileData {
+		private String url;
+		private int pageNum;
+	}
+	
+	public EvaluationContentComposite(Composite parent, String tenderId) {
+		super(parent, SWT.NONE);
+		this.tenderId = tenderId;
+		
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.verticalSpacing = 0;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		Composite composite_5 = new Composite(this, SWT.NONE);
+		composite_5.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
+		GridLayout gl_composite_5 = new GridLayout(2, false);
+		gl_composite_5.marginHeight = 0;
+		gl_composite_5.marginWidth = 0;
+		composite_5.setLayout(gl_composite_5);
+		
+		Composite composite = new Composite(composite_5, SWT.NONE);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.BOTTOM, true, true, 1, 1));
+		RowLayout rl_composite = new RowLayout(SWT.HORIZONTAL);
+		rl_composite.marginBottom = 0;
+		rl_composite.marginTop = 0;
+		composite.setLayout(rl_composite);
+		
+		TabHandler<RectangleRadioButton> handler = new TabHandler<>(composite, t -> new RectangleRadioButton(t, SWT.NONE));
+		
+		Composite composite_6 = new Composite(composite_5, SWT.NONE);
+		GridLayout gl_composite_6 = new GridLayout(1, false);
+		gl_composite_6.marginHeight = 4;
+		composite_6.setLayout(gl_composite_6);
+		
+		ELink link = new ELink(composite_6, SWT.NONE);
+		link.addMouseListener(MouseListener.mouseUpAdapter($ -> showFile.replace(t -> !t)));
+		link.setText("切换视图");
+		showSwitch.bind(link::setVisible);
+		
+		ESepator label_1 = new ESepator(this, SWT.HORIZONTAL);
+		label_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		label_1.setBackground(ColorConstants.SKIN_BG);
+		
+		StackLayout stackLayout = new StackLayout();
+		
+		Composite composite_1 = new Composite(this, SWT.NONE);
+		composite_1.setLayout(stackLayout);
+		composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		
+		Consumer<Composite> topControl = t -> {
+			stackLayout.topControl = t;
+			composite_1.layout();
+		};
+		
+		ModelDataComposite composite_2 = new ModelDataComposite(composite_1, tenderId);
+		
+		Composite composite_3 = new Composite(composite_1, SWT.NONE);
+		composite_3.setLayout(new FillLayout(SWT.HORIZONTAL));
+		
+		PdfFileView load = Global.PDF_FILE_VIEW.load(composite_3, SWT.NONE);
+		load.setFileNotExistMessage("文件不存在,请检查是否已下载投标文件!");
+		pdfFileData.bind(t -> load.openFile(t.url, t.pageNum));
+		
+		Composite composite_4 = new Composite(composite_1, SWT.NONE);
+		composite_4.setLayout(new GridLayout(1, false));
+		
+		Label label = new Label(composite_4, SWT.WRAP);
+		label.setForeground(SWTResourceManager.getColor(200, 200, 200));
+		label.setFont(SWTResourceManager.getFont("宋体", 20, SWT.BOLD));
+		label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 1));
+		
+		tips.bind(t -> {
+			label.setText(t);
+			label.getParent().layout();
+		});
+		
+		showFile.bind(t -> {
+			if (t) topControl.accept(composite_3);
+			else topControl.accept(composite_2);
+		});
+		
+		evaluationContentData.bind(d -> {
+			showSwitch.set(false);
+			handler.start();
+			if (CollectionUtils.isNull(d.evaluationContentList)) {
+				rootNodeChapter(handler, d.factorTypeEnum, t -> {
+					showFile.set(true);
+					RxSwt.run(() -> getFilePath(d.supplierId, t.type)).checkWidget(this).exe(pdfFileData::set);
+				});
+			} else {
+				handler.listHand(d.evaluationContentList, EvaluationContent::getEvalPointName, t -> {
+					showSwitch.set(false);
+					switch (DataCategoryEnum.MAP.getOrDefault(t.getDataCategory(), DataCategoryEnum.NULL)) {
+						case MD:
+							getModelData(t.getRelChapterType(), d.supplierId, md -> {
+								if (md == null) {
+									topControl.accept(composite_4);
+									tips.set("当前供应商未检测到" + t.getEvalPointName() + ",请检查是否已解析结构化数据!");
+								} else {
+									if (ModelDataTypeEnum.EQ_ProjectLeader.getKey().equals(md.getRelChapterType())) {
+										showSwitch.set(true);
+										showFile.set(false);
+										composite_2.refresh(t, md);
+										RxSwt.run(() -> getFilePath(d.supplierId, "EnterpriseQualification_technology")).checkWidget(this).exe(pdfFileData::set);
+									} else {
+										showFile.set(false);
+										composite_2.refresh(t, md);
+									}
+								}
+							});
+							break;
+						case TDI:
+						case TT:
+						case NULL:
+							showFile.set(true);
+							RxSwt.run(() -> getFilePath(d.supplierId, t.getRelChapterType())).checkWidget(this).exe(pdfFileData::set);
+							break;
+					}
+				});
+			}
+			handler.end();
+		});
+	}
+	
+	private void rootNodeChapter(TabHandler<RectangleRadioButton> handler, EvaluationFactorTypeEnum factorTypeEnum, Consumer<RootNodeChapterData> callback) {
+		handler.listHand(initRootNodeChapterList(factorTypeEnum).map(t -> {
+			String[] split = t.split("-", 2);
+			RootNodeChapterData chapterData = new RootNodeChapterData();
+			chapterData.type = split[0];
+			chapterData.name = split[1];
+			return chapterData;
+		}).collect(Collectors.toList()), t -> t.name, callback);
+	}
+	
+	private void getModelData(String _relChapterType, String supplierId, Consumer<ModelData> consumer) {
+		RelChapterTypeHandler typeHandler = new RelChapterTypeHandler(_relChapterType);
+		Optional<ModelDataTypeEnum> modelDataTypeEnum = Optional.of(typeHandler.getRelChapterType()).map(ModelDataTypeEnum.MAP::get);
+		String relChapterType = modelDataTypeEnum.map(ModelDataTypeEnum.EQ_ProjectLeader::equals).orElse(false) ? typeHandler.getRelChapterType() : _relChapterType;
+		RxSwt.run(() -> modelDataService.getModelData(tenderId, supplierId, relChapterType, relChapterType)).checkWidget(this).exe(consumer);
+	}
+	
+	private Stream<String> initRootNodeChapterList(EvaluationFactorTypeEnum factorTypeEnum) {
+		if (EvaluationFactorTypeEnum.BUSINESS == factorTypeEnum) {
+			return Stream.of("Business-商务标");
+		}
+		if (EvaluationFactorTypeEnum.TECHNOLOGY == factorTypeEnum) {
+			return Stream.of("Technology-技术标");
+		}
+		return Stream.of("Business-商务标", "Technology-技术标", "Price-报价");
+	}
+	
+	public void refresh(String supplierId, String factorCode, EvaluationFactorTypeEnum factorTypeEnum) {
+		RxSwt.run(() -> {
+			EvaluationContentData evaluationContentData = new EvaluationContentData();
+			evaluationContentData.supplierId = supplierId;
+			evaluationContentData.factorTypeEnum = factorTypeEnum;
+			evaluationContentData.evaluationContentList = evaluationContentService.getEvaluationContentListByFactorCode(tenderId, factorCode);
+			return evaluationContentData;
+		}).checkWidget(this).exe(evaluationContentData::set);
+	}
+	
+	private PdfFileData getFilePath(String supplierId, String relChapterType) {
+		BidFileIndexTreeXmlParse bidFileIndexTreeXmlParse = new BidFileIndexTreeXmlParse(Constants.getBidFilePath(tenderId, supplierId), relChapterType);
+		PdfFileData pdfFileData = new PdfFileData();
+		pdfFileData.url = bidFileIndexTreeXmlParse.getRootNodeFilePath();
+		pdfFileData.pageNum = bidFileIndexTreeXmlParse.getPageNumInGenerateFile();
+		return pdfFileData;
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c77d17c962b2b71302921b3ed96cdc2e5470bdd
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidComposite.java
@@ -0,0 +1,178 @@
+package com.gx.obe.struct.composite;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.core.utils.FileDialogUtils;
+import org.eclipse.swt.core.utils.WidgetUtils;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.call.Call;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.business.entity.Result;
+import com.gx.obe.common.widget.button.EvaluationButton;
+import com.gx.obe.common.widget.shell.ProgressMessageDialog;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.components.core.enumeration.CommonEnum;
+import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+import com.gx.obe.message.Messages;
+import com.gx.obe.step.service.StepService;
+import com.gx.obe.struct.Global;
+import com.gx.obe.struct.ProgressMessageTangent;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.struct.handler.FactorClearBidContentStepHandler;
+import com.gx.obe.struct.inters.IFactorClearBidContent;
+import com.gx.obe.struct.listener.CellDoubleClickListener;
+import com.gx.obe.struct.listener.GoBackListener;
+import com.gx.obe.util.utils.StringUtils;
+import com.gx.obe.web.entity.auth.AuthUser;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+
+public class FactorClearBidComposite extends Composite {
+	
+	private final SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	
+	private final List<GoBackListener> goBackListeners = new ArrayList<>();
+	
+	private final TenderProjectEntity tenderProject;
+	private final EvaluationStep evaluationStep;
+	private final AuthUser curUser;
+	
+	private final Prop<CellDoubleClickListener> cellDoubleClickListener = new Prop<>();
+	private final Prop<String> reviewContent = new Prop<>();
+	private final Prop<Boolean> calculate = new Prop<>(false);
+	private final Call refresh = new Call();
+	
+	public FactorClearBidComposite(Composite parent, TenderProjectEntity tenderProject, EvaluationStep evaluationStep, AuthUser curUser) {
+		super(parent, SWT.NONE);
+		this.tenderProject = tenderProject;
+		this.evaluationStep = evaluationStep;
+		this.curUser = curUser;
+		setLayout(new GridLayout(1, false));
+		
+		FactorClearBidContentComposite composite = new FactorClearBidContentComposite(this, Optional.ofNullable(tenderProject).map(TenderProjectEntity::getId).orElse(null), evaluationStep);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		cellDoubleClickListener.bind(composite::addCellDoubleClickListeners);
+		refresh.bind(composite::refresh);
+		reviewContent.bind(composite::refreshCell);
+		
+		Composite composite_2 = new Composite(this, SWT.NONE);
+		composite_2.setLayout(new GridLayout(3, false));
+		composite_2.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
+		
+		EvaluationButton button_2 = new EvaluationButton(composite_2, SWT.NONE);
+		button_2.setText("重新计算评议意见");
+		button_2.addMouseListener(MouseListener.mouseUpAdapter(e -> calculateOpinionAction()));
+		calculate.bind(t -> WidgetUtils.setControlVisible(button_2, t));
+		
+		EvaluationButton button = new EvaluationButton(composite_2, SWT.NONE);
+		button.setText("导出评议表");
+		button.addMouseListener(MouseListener.mouseUpAdapter(e -> exportEvaluationTable()));
+		
+		EvaluationButton button_1 = new EvaluationButton(composite_2, SWT.NONE);
+		button_1.setText(Messages.Button_submitEvaluationResult);
+		button_1.addMouseListener(MouseListener.mouseUpAdapter(e -> submitAction()));
+		
+		calculate.bind(c -> {
+			if (!c) return;
+			if (CommonEnum.YES.equals(evaluationStep.getEvaluationParamByKey(EvaluationStepEnum.COMPLETE_CALCULATION))) return;
+			calculateOpinion();
+		});
+		
+		calculate.set(evaluationStep != null && EvaluationFactorTypeEnum.COMPLIANCE == EvaluationFactorTypeEnum.MAP.get(evaluationStep.getEvaluationParamByKey(EvaluationStepEnum.EVALUATION_FACTOR_TYPE)));
+	}
+	
+	public void refresh() {
+		refresh.exe();
+	}
+	
+	public void refreshCell(String content) {
+		reviewContent.set(content);
+	}
+	
+	public void addCellDoubleClickListeners(CellDoubleClickListener cellDoubleClickListener) {
+		this.cellDoubleClickListener.set(cellDoubleClickListener);
+	}
+	
+	public void addGoBackListener(GoBackListener goBackListener) {
+		this.goBackListeners.add(goBackListener);
+	}
+	
+	private void calculateOpinionAction() {
+		if (MessageDialog.openConfirm(getShell(), "重新计算评议意见操作会对当前录入的评议意见进行覆盖,是否确认重新计算?")) {
+			calculateOpinion();
+		}
+	}
+	
+	private void calculateOpinion() {
+		RxSwt.run(() -> {
+			return supplierEvaluationFactorService.calculateFactorClearBidOpinion(evaluationStep.getId());
+		}).setTangent(new ProgressMessageTangent(getShell(), "正在自动生成评议意见...")).checkWidget(this).exe(t -> {
+			if (t == null) {
+				MessageDialog.openWarning(getShell(), "接口调用失败!");
+				return;
+			}
+			if (Result.SUCCESS != t.getCode()) {
+				MessageDialog.openWarning(getShell(), t.getMsg());
+				return;
+			}
+			refresh();
+		});
+	}
+	
+	private void exportEvaluationTable() {
+		String directorySavePath = FileDialogUtils.getDirectorySavePath(Messages.Tips_selectExportDic, "[" + tenderProject.getTenderNo() + "]" + tenderProject.getTenderName());
+		if (StringUtils.isEmpty(directorySavePath)) {
+			return;
+		}
+		ProgressMessageDialog messageDialog = new ProgressMessageDialog(getShell(), false, -1, null);
+		messageDialog.setTitle("导出评议意见表");
+		
+		IFactorClearBidContent factorClearBidContent = new FactorClearBidContentStepHandler(evaluationStep);
+		
+		Map<String, Object> dateMap = new HashMap<>();
+		dateMap.put("factorClearBidContent", factorClearBidContent);
+		
+		Global.EXCEL_REPORT.generate(tenderProject, "FactorClearBidContent.xlsx", directorySavePath, dateMap).then(t -> {
+			messageDialog.message(Messages.Tips_exportSuccess, 1);
+			messageDialog.finish(true);
+		}, e -> {
+			messageDialog.message(e.getMessage(), -1);
+			messageDialog.finish(false);
+		});
+		messageDialog.open();
+	}
+	
+	/**
+	 * @Description: 提交事件
+	 * @author chenxw
+	 */
+	private void submitAction() {
+		String message = MessageFormat.format(Messages.Tips_submitEvaluationResult, evaluationStep.getStepName());
+		if (!MessageDialog.openConfirm(getShell(), Messages.Button_submitEvaluationResult, message, Messages.Button_confirmComplate, Messages.Button_continueEvaluation)) {
+			return;
+		}
+		if (!StepService.submitEvaluationStep(tenderProject.getId(), evaluationStep.getId(), curUser.getId())) {
+			MessageDialog.openInformation(getShell(), Messages.Tips_submitEvalResultFailed);
+			return;
+		}
+		goBackListeners.forEach(l -> l.goBackAction());
+	}
+	
+	
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidContentComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidContentComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..43779aec2f011696350301ef406404c15c0baa20
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidContentComposite.java
@@ -0,0 +1,130 @@
+package com.gx.obe.struct.composite;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.utils.WidgetUtils;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.struct.beans.IntelligentEvalDO;
+import com.gx.obe.struct.beans.ScoreOptionsDO;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.struct.listener.CellDoubleClickListener;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+import com.gx.obe.web.vo.FactorClearBidContent;
+
+public class FactorClearBidContentComposite extends Composite {
+	
+	private final SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	
+	private final EvaluationStep evaluationStep;
+	
+	private final Prop<CellDoubleClickListener> cellDoubleClickListener = new Prop<>();
+	private final Prop<Boolean> showSupplierOpinion = new Prop<>(true);
+	private final Prop<FactorClearBidContent> factorClearBidContent = new Prop<>();
+	private final Prop<String> reviewContent = new Prop<>();
+	
+	public FactorClearBidContentComposite(Composite parent, String tenderId, EvaluationStep evaluationStep) {
+		super(parent, SWT.NONE);
+		this.evaluationStep = evaluationStep;
+		
+		setLayout(new GridLayout(1, false));
+		
+		SelfEvaluatesComposite composite = new SelfEvaluatesComposite(this, SupplierEvaluationFactor::getOpinion);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		composite.setTitleName("标书评议意见");
+		cellDoubleClickListener.bind(composite::addCellDoubleClickListeners);
+		factorClearBidContent.bind(t -> composite.refresh(tenderId, t.getSupplierList(), t.getFactorList(), t.getSupplierEvaluationFactorList()));
+		reviewContent.bind(composite::refreshCell);
+		
+		SelfEvaluatesComposite composite_1 = new SelfEvaluatesComposite(this, SupplierEvaluationFactor::getFactorResponse);
+		composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		composite_1.setTitleName("标书清标意见");
+		factorClearBidContent.bind(t -> {
+			if (showSupplierOpinion.get()) composite_1.refresh(tenderId, t.getSupplierList(), t.getFactorList(), t.getSupplierEvaluationFactorList());
+		});
+		showSupplierOpinion.bind(t -> WidgetUtils.setControlVisible(composite_1, t));
+	}
+	
+	public void refresh() {
+		showSupplierOpinion.set(EvaluationFactorTypeEnum.COMPLIANCE != EvaluationFactorTypeEnum.MAP.get(evaluationStep.getEvaluationParamByKey(EvaluationStepEnum.EVALUATION_FACTOR_TYPE)));
+		FactorClearBidContent  actorClearBidContent1  = supplierEvaluationFactorService.getFactorClearBidContent(evaluationStep.getId());
+		Map<String, IntelligentEvalDO> evaluationFactorMap = new HashMap<String, IntelligentEvalDO>();
+//		Set<String> factorCodeSet = new HashSet<>();
+		StringBuffer buffer = new StringBuffer();
+		for(EvaluationFactor evaluationFactor : actorClearBidContent1.getFactorList()) {
+			setBuffer(buffer, evaluationFactorMap, evaluationFactor);
+		}
+		String keyBuffer = buffer.toString();//智能指标code拼接
+		if(null != actorClearBidContent1.getSupplierEvaluationFactorList()) {
+			for(SupplierEvaluationFactor supplierEvaluationFactor : actorClearBidContent1.getSupplierEvaluationFactorList()) {
+				if(keyBuffer.contains(supplierEvaluationFactor.getFactorCode())) {
+					List<ScoreOptionsDO> scoreOptionsDOList = evaluationFactorMap.get(supplierEvaluationFactor.getFactorCode()).getScoreOptionsDOList();
+					if(null != scoreOptionsDOList && scoreOptionsDOList.size() > 0) {
+						scoreOptionsDOList.forEach(t->{
+							if(t.getScoreItemId().equals(supplierEvaluationFactor.getFactorResponse())) {
+								
+								supplierEvaluationFactor.setFactorResponse(t.getName());
+								// TODO 
+								
+							}
+							if(null == supplierEvaluationFactor.getOpinion()) {
+								supplierEvaluationFactor.setOpinion(t.getName());
+							}else 
+							if(t.getScoreItemId().equals(supplierEvaluationFactor.getOpinion())) {
+								supplierEvaluationFactor.setOpinion(t.getName());
+							}
+						});
+					}
+				}
+			}
+		}
+		RxSwt.run(() -> 
+		actorClearBidContent1).checkWidget(this).exe(factorClearBidContent::set);
+	}
+	
+	/**
+	 * @param buffer
+	 * @param map
+	 * @param evaluationFactor
+	 * 设置智能评审指标
+	 */
+	private void setBuffer(StringBuffer buffer, Map<String, IntelligentEvalDO> map, EvaluationFactor evaluationFactor) {
+		if(null != evaluationFactor.getChildFactorList() && evaluationFactor.getChildFactorList().size() > 0) {
+			for(EvaluationFactor childrenEvaluationFactor : evaluationFactor.getChildFactorList()) {
+				setBuffer(buffer, map, childrenEvaluationFactor);
+			}
+		
+		}else {
+			if(null != evaluationFactor.getIntelligentEval()) {
+				IntelligentEvalDO intelligentEvalDO = JsonUtil.jsonToBean(evaluationFactor.getIntelligentEval(), IntelligentEvalDO.class);
+				if(null != intelligentEvalDO && null != intelligentEvalDO.getFactorModel() && intelligentEvalDO.getFactorModel().contains("F")) {
+					map.put(evaluationFactor.getFactorCode(), intelligentEvalDO);
+					buffer.append("#" +evaluationFactor.getFactorCode() + "#");
+				}
+			}
+		}
+	}
+	public void refreshCell(String content) {
+		reviewContent.set(content);
+	}
+	
+	public void addCellDoubleClickListeners(CellDoubleClickListener cellDoubleClickListener) {
+		this.cellDoubleClickListener.set(cellDoubleClickListener);
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidEvaluationComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidEvaluationComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..15fe04c1faa54c72af73d94d33114ac45019ebe9
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidEvaluationComposite.java
@@ -0,0 +1,173 @@
+package com.gx.obe.struct.composite;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+
+import com.gx.obe.WebserviceConstants;
+import com.gx.obe.bind.call.Call;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.common.widget.button.EvalLeftButton;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+import com.gx.obe.config.ConfigConstants;
+import com.gx.obe.config.utils.PropertiesUtils;
+import com.gx.obe.http.HttpResponse;
+import com.gx.obe.http.Status;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.step.composite.EvaluationComposite;
+import com.gx.obe.struct.Activator;
+import com.gx.obe.struct.dialog.AuxevaluationFullScreenDialog;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.util.utils.StringUtil;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.utils.NetworkRequest;
+import com.gx.obe.web.utils.ResultStatus;
+import com.swtdesigner.ResourceManager;
+
+import net.sf.json.JSONObject;
+
+public class FactorClearBidEvaluationComposite extends EvaluationComposite {
+	
+	private final Call clearBidRefresh = new Call();
+	private final Prop<FactorClearBidData> factorClearBidData = new Prop<>();
+	private final Prop<Boolean> showMainView = new Prop<>(true);
+	private final Prop<String> reviewContent = new Prop<>();
+	
+	private SupplierEvaluationFactor supplierEvaluationFactor;
+	
+	private class FactorClearBidData {
+		private EvaluationFactor evaluationFactor;
+		private SupplierEvaluationFactor supplierEvaluationFactor;
+	}
+	
+	public FactorClearBidEvaluationComposite(Composite parent, TenderProjectEntity tenderProject, EvaluationStep evaluationStep) {
+		super(parent, tenderProject, evaluationStep);
+		
+		EvalLeftButton button = new EvalLeftButton(getLeftToolComposite(), SWT.SELECTED);
+		button.addMouseListener(MouseListener.mouseUpAdapter(e -> showAuxevaluationFullScreen()));
+		button.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
+		button.setImage(ResourceManager.getPluginImage(Activator.PLUGIN_ID, "icons/auxevaluation.png"));
+		button.setToolTipText("辅助评标");
+		
+		StackLayout stackLayout = new StackLayout();
+		
+		Composite composite = new Composite(getEvaluatoinComposite(), SWT.NONE);
+		composite.setLayout(stackLayout);
+		
+		FactorClearBidComposite composite_1 = new FactorClearBidComposite(composite, tenderProject, evaluationStep, curUser);
+		composite_1.addCellDoubleClickListeners(this::cellDoubleClicked);
+		composite_1.addGoBackListener(super::goBackAction);
+		clearBidRefresh.bindExe(composite_1::refresh);
+		reviewContent.bind(composite_1::refreshCell);
+		
+		EvaluationFactorTypeEnum factorTypeEnum = EvaluationFactorTypeEnum.MAP.get(evaluationStep.getEvaluationParamByKey(EvaluationStepEnum.EVALUATION_FACTOR_TYPE));
+		
+		ClearBidReviewEntryComposite composite_2 = new ClearBidReviewEntryComposite(composite, tenderProject.getId());
+		composite_2.addReturnListener(this::returnAction);
+		factorClearBidData.bind(t -> composite_2.refresh(t.evaluationFactor, t.supplierEvaluationFactor, factorTypeEnum));
+		
+		showMainView.bindExe(t -> {
+			stackLayout.topControl = t ? composite_1 : composite_2;
+			composite.layout();
+		});
+	}
+	
+	private void showAuxevaluationFullScreen() {
+		new Thread() {
+			public void run(){	
+				Display.getDefault().syncExec(new Runnable(){
+					public void run(){
+						String stPlatformUrl = PropertiesUtils.getProperty(ConfigConstants.SERVER_URL, "");
+						if(!stPlatformUrl.endsWith("/")){
+							stPlatformUrl = stPlatformUrl + "/";
+						}
+						stPlatformUrl = stPlatformUrl + PropertiesUtils.getWebserviceProperty(WebserviceConstants.GET_TB_TOKEN, "tBBaseNoticeController.do?forDTbeTokenUser");
+						Map<String, Object> param = new HashMap<String, Object>();
+						param.put("userName",  Constants.USER.getUserAccount());
+						String getWebserviceXml = NetworkRequest.get(stPlatformUrl, param);
+						boolean flag = false;
+						String obj = null;
+						try {
+							JSONObject root = JSONObject.fromObject(getWebserviceXml);
+							boolean result = (boolean) root.get("success");	
+							if(result){
+								flag = true;
+								obj = (String)root.get("obj");
+							}
+						} catch (Exception e) {
+						}
+						if(flag && null != obj) {
+							new AuxevaluationFullScreenDialog(getShell(), tenderProject.getStageId(), obj).open();
+						}
+					}
+				});
+				
+			}
+		}.start();
+	}
+
+	private void cellDoubleClicked(EvaluationFactor evaluationFactor, SupplierEvaluationFactor supplierEvaluationFactor) {
+		showMainView.set(false);
+		this.supplierEvaluationFactor = supplierEvaluationFactor;
+		FactorClearBidData factorClearBidData = new FactorClearBidData();
+		factorClearBidData.evaluationFactor = evaluationFactor;
+		factorClearBidData.supplierEvaluationFactor = supplierEvaluationFactor;
+		this.factorClearBidData.set(factorClearBidData);
+	}
+	
+	private void returnAction() {
+		showMainView.set(true);
+		reviewContent.set(supplierEvaluationFactor.getOpinion());
+	}
+	
+	@Override
+	protected void goBackAction() {
+		if (showMainView.get()) {
+			super.goBackAction();
+		} else {
+			returnAction();
+		}
+	}
+	
+	@Override
+	protected void initButtonComposite() {}
+	
+	@Override
+	protected void refreshEvaluationResult() {
+		clearBidRefresh.exe();
+	}
+	
+	@Override
+	protected boolean saveEvaluationResult() {
+		return false;
+	}
+	
+	@Override
+	protected String checkEvaluationResult() {
+		return null;
+	}
+
+	@Override
+	protected void createEvaluatoinComposite(Composite evaluatoinComposite) {
+		// TODO Auto-generated method stub
+		
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidEvaluationResultComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidEvaluationResultComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..e0c63b6f250d222999327e05f5d5995958e50e2e
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FactorClearBidEvaluationResultComposite.java
@@ -0,0 +1,28 @@
+package com.gx.obe.struct.composite;
+
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.step.composite.EvaluationResultSingleComposite;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+
+public class FactorClearBidEvaluationResultComposite extends EvaluationResultSingleComposite {
+	
+	public FactorClearBidEvaluationResultComposite(Composite parent, TenderProjectEntity tenderProject, EvaluationStep evaluationStep, String userId) {
+		super(parent, tenderProject, evaluationStep, userId);
+		new FactorClearBidContentComposite(getResultComposite(), tenderProject.getId(), evaluationStep).refresh();
+	}
+
+	@Override
+	protected void createResultComposite(Composite tableComposite) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	@Override
+	protected void refreshResultComposite() {
+		// TODO Auto-generated method stub
+		
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/FileButton.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FileButton.java
new file mode 100644
index 0000000000000000000000000000000000000000..db9f8004b65e62e2601bbb59f5c138131bab91bc
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/FileButton.java
@@ -0,0 +1,152 @@
+package com.gx.obe.struct.composite;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.core.widgets.EMenu;
+import org.eclipse.swt.core.widgets.EMenu.ClickListener;
+import org.eclipse.swt.core.widgets.ImageButton;
+import org.eclipse.swt.events.MenuDetectEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.call.Callback;
+import com.gx.obe.common.file.utils.FileUtils;
+import com.gx.obe.common.icons.IconsActivator;
+import com.gx.obe.util.utils.RuntimeUtils;
+import com.swtdesigner.ResourceManager;
+import com.swtdesigner.SWTResourceManager;
+
+public class FileButton extends Composite {
+	
+	protected File file;
+	
+	protected ImageButton imageButton;
+	
+	private List<ItemParam> itemParamList = new ArrayList<>();
+	
+	public FileButton(Composite parent, File file) {
+		this(parent, file, Optional.of(file).map(File::getName).get());
+	}
+	
+	/**
+	 * @wbp.parser.constructor
+	 */
+	public FileButton(Composite parent, File file, String fileName) {
+		super(parent, SWT.NONE);
+		
+		this.file = file;
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		imageButton = new ImageButton(this, SWT.BOTTOM | SWT.CENTER | SWT.WRAP);
+		GridData gd_imageButton = new GridData(SWT.CENTER, SWT.FILL, false, true, 1, 1);
+		gd_imageButton.widthHint = 100;
+		imageButton.setLayoutData(gd_imageButton);
+		
+		imageButton.setForeground(SWTResourceManager.getColor(100, 100, 100));
+		imageButton.setFont(SWTResourceManager.getFont("微软雅黑", 9, SWT.NORMAL));
+		
+		imageButton.setActiveBorderColor(SWTResourceManager.getColor(77, 163, 19));
+		imageButton.setActiveForeground(SWTResourceManager.getColor(100, 100, 100));
+		imageButton.setActiveBgColor(SWTResourceManager.getColor(205, 225, 205));
+		
+		imageButton.setGAP(0);
+		imageButton.setAlpha(120);
+		imageButton.setArcWidth(6);
+		
+		imageButton.setText(fileName);
+		imageButton.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, getFileImagePath(fileName)));
+		imageButton.addMouseListener(MouseListener.mouseDoubleClickAdapter(this::openFile));
+		imageButton.addMenuDetectListener(this::menuDetect);
+	}
+	
+	/**
+	 * @Description:  添加菜单项
+	 * @author guoyr
+	 * @param menuItemText
+	 * @param menuItemImage
+	 * @param enabled
+	 * @param callBack
+	 */
+	public void addMenuItem(String menuItemText, Image menuItemImage, boolean enabled, Callback clickListener) {
+		itemParamList.add(new ItemParam(menuItemText, menuItemImage, enabled, clickListener));
+	}
+	
+	private void menuDetect(MenuDetectEvent e) {
+		EMenu menu = new EMenu(getShell());
+		menu.addMenuItem("打开", null, true, new ClickListener() {
+			public void click() {
+				openFile(null);
+			}
+		});
+		for (ItemParam itemParam : itemParamList) {
+			menu.addMenuItem(itemParam.menuItemText, itemParam.menuItemImage, itemParam.enabled, new ClickListener() {
+				public void click() {
+					itemParam.clickListener.call();
+				}
+			});
+		}
+		menu.open();
+	}
+	
+	
+	
+	protected void openFile(MouseEvent e) {
+		if (!file.exists()) {
+			MessageDialog.openShortMessage("文件不存在!");
+			return;
+		}
+		RuntimeUtils.openFIle(file);
+	}
+	
+	/**
+	 * @Description:
+	 * @author mazc
+	 * @param fileName
+	 * @return
+	 */
+	private String getFileImagePath(String fileName) {
+		switch (FileUtils.funGetSuffix.apply(fileName)) {
+			case "pdf": return "icons/pdf_64.png";
+			case "xml": return "icons/xml_64.png";
+			case "doc": case "docx": return "icons/word_64.png";
+			case "xls": case "xlsx": return "icons/excel_64.png";
+			case "png": case "bmp": case "gif": case "psd": case "jpg": case "jpeg": return "icons/image_64.png";
+			default: return "icons/unknown_64.png";
+		}
+	}
+	
+	public File getFile() {
+		return file;
+	}
+
+	static class ItemParam {
+		
+		String menuItemText;
+		Image menuItemImage;
+		boolean enabled;
+		Callback clickListener;
+		
+		public ItemParam(String menuItemText, Image menuItemImage, boolean enabled, Callback clickListener) {
+			this.menuItemText = menuItemText;
+			this.menuItemImage = menuItemImage;
+			this.enabled = enabled;
+			this.clickListener = clickListener;
+		}
+		
+	}
+	
+}
+
+
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/ModelDataComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/ModelDataComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..22cf2745aafd7473be7e546fe7fe6234d4534f47
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/ModelDataComposite.java
@@ -0,0 +1,129 @@
+package com.gx.obe.struct.composite;
+
+import java.util.Optional;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.listener.RoundBorderLineListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.call.Call;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.struct.beans.ModelData;
+import com.gx.obe.struct.enums.ModelDataTypeEnum;
+import com.gx.obe.struct.factory.ModelDataFactory;
+import com.gx.obe.struct.handler.RelChapterTypeHandler;
+import com.gx.obe.struct.inters.IModelData;
+import com.gx.obe.struct.inters.IModelDataDetail;
+import com.gx.obe.web.entity.evaluation.EvaluationContent;
+import com.swtdesigner.SWTResourceManager;
+
+public class ModelDataComposite extends Composite {
+	
+	private final Prop<String> title = new Prop<>();
+	private final Prop<Integer> count = new Prop<>();
+	private final Prop<ModelDataTypeEnum> modelDataTypeEnum = new Prop<>();
+	private final Prop<ModelData> modelData = new Prop<>();
+	
+	private final Call call = new Call();
+	
+	public ModelDataComposite(Composite parent, String tenderId) {
+		super(parent, SWT.NONE);
+		
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.verticalSpacing = 0;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		Composite composite = new Composite(this, SWT.NONE);
+		GridLayout gl_composite = new GridLayout(1, false);
+		gl_composite.marginTop = 5;
+		gl_composite.marginHeight = 0;
+		gl_composite.marginWidth = 0;
+		composite.setLayout(gl_composite);
+		GridData gd_composite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_composite.heightHint = 400;
+		composite.setLayoutData(gd_composite);
+		
+		Composite composite_2 = new Composite(composite, SWT.NONE);
+		GridLayout gl_composite_2 = new GridLayout(2, false);
+		gl_composite_2.marginWidth = 0;
+		composite_2.setLayout(gl_composite_2);
+		composite_2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		Label lblNewLabel = new Label(composite_2, SWT.NONE);
+		lblNewLabel.setFont(SWTResourceManager.getFont("Microsoft YaHei UI", 10, SWT.BOLD));
+		title.bind(t -> {
+			lblNewLabel.setText(t);
+			composite_2.layout();
+		});
+		
+		Composite composite_4 = new Composite(composite_2, SWT.NONE);
+		composite_4.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		GridLayout gl_composite_4 = new GridLayout(3, false);
+		gl_composite_4.marginHeight = 0;
+		composite_4.setLayout(gl_composite_4);
+		
+		Label lblNewLabel_1 = new Label(composite_4, SWT.NONE);
+		lblNewLabel_1.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, false, false, 1, 1));
+		lblNewLabel_1.setText("共有");
+		
+		Label lblNewLabel_2 = new Label(composite_4, SWT.NONE);
+		lblNewLabel_2.setForeground(SWTResourceManager.getColor(255, 93, 0));
+		lblNewLabel_2.setFont(SWTResourceManager.getFont("Microsoft YaHei UI", 10, SWT.BOLD));
+		count.bind(t -> {
+			lblNewLabel_2.setText(String.valueOf(t));
+			composite_4.layout();
+		});
+		
+		Label lblNewLabel_3 = new Label(composite_4, SWT.NONE);
+		lblNewLabel_3.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, false, false, 1, 1));
+		title.bind(t -> {
+			lblNewLabel_3.setText("条" + t + "信息");
+			composite_4.layout();
+		});
+		
+		Composite composite_3 = new Composite(composite, SWT.NONE);
+		FillLayout fl_composite_3 = new FillLayout(SWT.HORIZONTAL);
+		fl_composite_3.marginHeight = 1;
+		fl_composite_3.marginWidth = 1;
+		composite_3.setLayout(fl_composite_3);
+		composite_3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		composite_3.addPaintListener(new RoundBorderLineListener(ColorConstants.BORDER_LINE_COLOR));
+		
+		ModelDataDetailComposite composite_1 = new ModelDataDetailComposite(this, tenderId);
+		composite_1.setLayout(new GridLayout(1, false));
+		GridData gd_composite_1 = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_composite_1.heightHint = 500;
+		composite_1.setLayoutData(gd_composite_1);
+		
+		IModelDataDetail modelDataDetail = composite_1.getModelDataDetail();
+		call.bind(() -> modelDataDetail.refreshTitle(""));
+		
+		modelDataTypeEnum.bind(t -> {
+			IModelData iModelData = ModelDataFactory.create(composite_3, modelDataDetail, t);
+			iModelData.setCountWrite(count::set);
+			modelData.bind(iModelData::refresh);
+		});
+	}
+	
+	public void refresh(EvaluationContent evaluationContent, ModelData modelData) {
+		Optional.of(evaluationContent).map(EvaluationContent::getEvalPointName).ifPresent(title::set);
+		Optional.of(evaluationContent).map(t -> {
+			return new RelChapterTypeHandler(t.getRelChapterType()).getRelChapterType();
+		}).map(ModelDataTypeEnum.MAP::get).ifPresent(modelDataTypeEnum::set);
+		this.modelData.set(modelData);
+		this.call.exe();
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/ModelDataDetailComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/ModelDataDetailComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..3eaf2bc1c4ac2636a89ceffaea2f13624cc45bfd
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/ModelDataDetailComposite.java
@@ -0,0 +1,147 @@
+package com.gx.obe.struct.composite;
+
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.widgets.ESepator;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.component.handler.TabHandler;
+import com.gx.obe.struct.inters.IModelDataDetail;
+import com.gx.obe.struct.widget.TabButton;
+import com.swtdesigner.SWTResourceManager;
+
+public class ModelDataDetailComposite extends Composite {
+	
+	private final Prop<String> titleName = new Prop<>();
+	
+	private final IModelDataDetail modelDataDetail;
+	
+	public ModelDataDetailComposite(Composite parent, String tenderId) {
+		super(parent, SWT.NONE);
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.verticalSpacing = 0;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		Composite composite = new Composite(this, SWT.NONE);
+		GridLayout gl_composite = new GridLayout(1, false);
+		gl_composite.marginHeight = 10;
+		composite.setLayout(gl_composite);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		Label lblNewLabel = new Label(composite, SWT.NONE);
+		lblNewLabel.setFont(SWTResourceManager.getFont("Microsoft YaHei UI", 10, SWT.BOLD));
+		lblNewLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
+		titleName.bind(t -> {
+			lblNewLabel.setText(t);
+			lblNewLabel.getParent().layout();
+		});
+		
+		ESepator label = new ESepator(this, SWT.HORIZONTAL);
+		label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		label.setBackground(SWTResourceManager.getColor(222, 234, 245));
+		label.setLineWidth(2);
+		
+		Composite composite_1 = new Composite(this, SWT.NONE);
+		GridLayout gl_composite_1 = new GridLayout(1, false);
+		gl_composite_1.verticalSpacing = 0;
+		gl_composite_1.marginHeight = 0;
+		gl_composite_1.marginWidth = 0;
+		composite_1.setLayout(gl_composite_1);
+		composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		
+		Composite composite_2 = new Composite(composite_1, SWT.NONE);
+		RowLayout rl_composite_2 = new RowLayout(SWT.HORIZONTAL);
+		rl_composite_2.marginBottom = 0;
+		rl_composite_2.marginTop = 0;
+		rl_composite_2.marginRight = 0;
+		rl_composite_2.marginLeft = 0;
+		rl_composite_2.spacing = 0;
+		composite_2.setLayout(rl_composite_2);
+		composite_2.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		TabHandler<TabButton> handler = new TabHandler<>(composite_2, TabButton::new);
+		
+		ESepator label_1 = new ESepator(composite_1, SWT.HORIZONTAL);
+		label_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		label_1.setBackground(SWTResourceManager.getColor(222, 234, 245));
+		
+		ScrolledComposite scrolledComposite = new ScrolledComposite(composite_1, SWT.H_SCROLL | SWT.V_SCROLL);
+		scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		scrolledComposite.setExpandHorizontal(true);
+		scrolledComposite.setExpandVertical(true);
+		
+		Composite composite_3 = new Composite(scrolledComposite, SWT.NONE);
+		GridLayout gl_composite_3 = new GridLayout(1, false);
+		gl_composite_3.marginHeight = 15;
+		gl_composite_3.marginWidth = 0;
+		composite_3.setLayout(gl_composite_3);
+		
+		StackLayout stackLayout = new StackLayout();
+		
+		Composite composite_4 = new Composite(composite_3, SWT.NONE);
+		composite_4.setLayout(stackLayout);
+		GridData gd_composite_4 = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_composite_4.widthHint = 700;
+		composite_4.setLayoutData(gd_composite_4);
+		scrolledComposite.setContent(composite_3);
+		scrolledComposite.setMinSize(composite_3.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+		
+		modelDataDetail = new IModelDataDetail() {
+			
+			@Override
+			public void refreshTitle(String title) {
+				titleName.set(title);
+			}
+			
+			public void addBasicSubpage(Function<Composite, Composite> initSub) {
+				handler.start();
+				addSubpage("基本信息", initSub);
+			}
+			
+			public void addSubpage(String name, Function<Composite, Composite> initSub) {
+				Composite subComposite = initSub.apply(composite_4);
+				handler.hand(name, () -> {
+					stackLayout.topControl = subComposite;
+					composite_4.layout();
+					composite_3.layout();
+					scrolledComposite.setContent(composite_3);
+					scrolledComposite.setMinSize(composite_3.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+				});
+			}
+			
+			public <T> void addAttachmentSubpage(Consumer<BiConsumer<String, String>> supplierIdAndBusinessIdConsumer) {
+				addSubpage("附件列表", p -> {
+					AttachmentComposite attachmentComposite = new AttachmentComposite(p, tenderId);
+					supplierIdAndBusinessIdConsumer.accept((supplierId, businessId) -> {
+						attachmentComposite.refresh(supplierId, businessId);
+					});
+					return attachmentComposite;
+				});
+				handler.end();
+			}
+			
+		};
+		
+	}
+	
+	public IModelDataDetail getModelDataDetail() {
+		return modelDataDetail;
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/SelfEvaluatesComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/SelfEvaluatesComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc46c8309d85f84a45913c2c8c2f90ce98b5db0b
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/SelfEvaluatesComposite.java
@@ -0,0 +1,254 @@
+package com.gx.obe.struct.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.core.listener.RoundBorderLineListener;
+import org.eclipse.swt.core.widgets.ELink;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.bind.utils.CollectorUtils;
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.common.icons.IconsActivator;
+import com.gx.obe.component.tree.ParseTrees;
+import com.gx.obe.component.utils.CompositeUtils;
+import com.gx.obe.message.Messages;
+import com.gx.obe.struct.listener.CellDoubleClickListener;
+import com.gx.obe.struct.tree.EvaluationFactorTree;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.swtdesigner.ResourceManager;
+import com.swtdesigner.SWTResourceManager;
+
+import de.kupzog.ktable.KTable;
+import de.kupzog.ktable.KTableCellDoubleClickListener;
+import de.kupzog.ktable.SWTX;
+import de.kupzog.ktable.model.CommonKtableCModel;
+import de.kupzog.ktable.renderers.FixedWrapCellRenderer;
+import de.kupzog.ktable.renderers.TextWrapCellRenderer;
+
+public class SelfEvaluatesComposite extends Composite {
+	
+	private final FixedWrapCellRenderer fixedWrapCellRenderer = new FixedWrapCellRenderer();
+	private final TextWrapCellRenderer textWrapCellRenderer = new TextWrapCellRenderer();
+	
+	{
+		fixedWrapCellRenderer.setFont(SWTResourceManager.getFont("微软雅黑", 9, SWT.NORMAL));
+		textWrapCellRenderer.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
+	}
+	
+	private final int headRow = 1;
+	
+	private final Prop<String> titleName = new Prop<>();
+	private final Prop<Integer> columnWidth = new Prop<Integer>().orElse(200);
+	private final Prop<TableData> tableData = new Prop<>();
+	private final Prop<String> reviewContent = new Prop<>();
+	private class TableData {
+		private List<Supplier> supplierList;
+		private List<EvaluationFactor> factorList;
+		private Map<String, Map<String, SupplierEvaluationFactor>> mapBySupplierIdByFactorCode;
+	}
+	
+	private int minWidth;
+	private final int maxWidth = 500;
+	
+	private final Function<SupplierEvaluationFactor, String> getOpinionFun;
+	
+	private final List<CellDoubleClickListener> cellDoubleClickListeners = new ArrayList<>();
+	
+	private Point point;
+	
+	public SelfEvaluatesComposite(Composite parent, Function<SupplierEvaluationFactor, String> getOpinionFun) {
+		super(parent, SWT.NONE);
+		this.getOpinionFun = getOpinionFun;
+		template();
+		mounted();
+	}
+	
+	private void template() {
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		Composite evaluationComposite = new Composite(this, SWT.NONE);
+		evaluationComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		evaluationComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		GridLayout gl_evaluationComposite = new GridLayout(1, false);
+		gl_evaluationComposite.verticalSpacing = 0;
+		gl_evaluationComposite.horizontalSpacing = 0;
+		gl_evaluationComposite.marginHeight = 0;
+		gl_evaluationComposite.marginWidth = 0;
+		evaluationComposite.setLayout(gl_evaluationComposite);
+		
+		Composite titleComposite = new Composite(evaluationComposite, SWT.NONE);
+		titleComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		titleComposite.setLayout(new GridLayout(4, false));
+		titleComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		Label titleLabel = new Label(titleComposite, SWT.NONE);
+		titleLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		titleLabel.setForeground(ColorConstants.NOTE_TIPS_COLOR);
+		titleLabel.setFont(SWTResourceManager.getFont("微软雅黑", 11, SWT.NORMAL));
+		titleName.bind(titleLabel::setText);
+		
+		ELink addWidthLink = new ELink(titleComposite, SWT.NONE);
+		addWidthLink.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/enlarge_width.png"));
+		addWidthLink.setText(Messages.Button_enlargeColumnWidth);
+		addWidthLink.addMouseListener(MouseListener.mouseUpAdapter($ -> columnWidth.replace(t -> {
+			t += 50;
+			if (t > maxWidth) t = maxWidth;
+			return t;
+		})));
+		addWidthLink.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		
+		ELink reduceWidthLink = new ELink(titleComposite, SWT.NONE);
+		reduceWidthLink.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/reduce_width.png"));
+		reduceWidthLink.setText(Messages.Button_reducedColumnWidth);
+		reduceWidthLink.addMouseListener(MouseListener.mouseUpAdapter($ -> columnWidth.replace(t -> {
+			t -= 50;
+			if (t < minWidth) t = minWidth;
+			return t;
+		})));
+		reduceWidthLink.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		
+		Composite evaluationTableComposite = new Composite(evaluationComposite, SWT.NONE);
+		evaluationTableComposite.addPaintListener(new RoundBorderLineListener(ColorConstants.BORDER_LINE_COLOR));
+		FillLayout fl_evaluationTableComposite = new FillLayout(SWT.HORIZONTAL);
+		fl_evaluationTableComposite.marginHeight = 1;
+		fl_evaluationTableComposite.marginWidth = 1;
+		evaluationTableComposite.setLayout(fl_evaluationTableComposite);
+		evaluationTableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		
+		tableData.bind(d -> {
+			CompositeUtils.disposeChildren(evaluationTableComposite);
+			KTable resultKTable = new KTable(evaluationTableComposite, SWTX.AUTO_SCROLL | SWTX.EDIT_ON_KEY);
+			
+			ParseTrees<EvaluationFactorTree> parseTrees = new ParseTrees<>(d.factorList.stream().map(t -> new EvaluationFactorTree(t, d.mapBySupplierIdByFactorCode, getOpinionFun)).collect(Collectors.toList()));
+			
+			resultKTable.addCellDoubleClickListener(new KTableCellDoubleClickListener() {
+				public void cellDoubleClicked(int col, int row, int statemask) {
+					point = new Point(row, col);
+					EvaluationFactorTree iTree = parseTrees.get(row - headRow);
+					cellDoubleClickListeners.forEach(l -> l.cellDoubleClicked(iTree.getEvaluationFactor(), iTree.getSupplierEvaluationFactorByKey(d.supplierList.get(col - parseTrees.getHeight()).getId())));
+				}
+				public void fixedCellDoubleClicked(int col, int row, int statemask) {}
+			});
+			
+			CommonKtableCModel commKTableModel = new CommonKtableCModel(resultKTable, headRow, parseTrees.getHeight(), parseTrees.getLeafCount(), d.supplierList.size());
+			resultKTable.setModel(commKTableModel);
+			
+			commKTableModel.addColSpan(0, 0, parseTrees.getHeight());
+			parseTrees.getHighSpanList().forEach(t -> commKTableModel.addColSpan(t.getLeafIndex() + headRow, t.getLevel(), t.getSpanCount()));
+			parseTrees.getWideSpanList().forEach(t -> commKTableModel.addRowSpan(t.getLeafIndex() + headRow, t.getLevel(), t.getSpanCount()));
+			
+			IntStream.range(0, parseTrees.getHeight() - 1).forEach(i -> commKTableModel.setColumnMaxWidth(i, 150));
+			commKTableModel.setColumnMaxWidth(parseTrees.getHeight() - 1, 200);
+			
+			commKTableModel.setCellContentRender((row, col) -> {
+				if (row < headRow) {
+					if (col < parseTrees.getHeight()) return "指标名称";
+					return d.supplierList.get(col - parseTrees.getHeight()).getSupplierName();
+				}
+				row -= headRow;
+				if (col < parseTrees.getHeight()) return parseTrees.getITree(col, row).getName();
+				return parseTrees.get(row).getValue(d.supplierList.get(col - parseTrees.getHeight()).getId());
+			});
+			
+			commKTableModel.setCellRender((row, col) -> {
+				return commKTableModel.isFixedCell(col, row) ? fixedWrapCellRenderer : textWrapCellRenderer;
+			});
+			
+			commKTableModel.setCellAlignmentRender((row, col) -> {
+				if (row < headRow) return SWTX.ALIGN_VERTICAL_CENTER | SWTX.ALIGN_HORIZONTAL_CENTER;
+				if (col < parseTrees.getHeight()) return SWTX.ALIGN_VERTICAL_CENTER | SWTX.ALIGN_HORIZONTAL_LEFT;
+				return SWTX.ALIGN_VERTICAL_TOP | SWTX.ALIGN_HORIZONTAL_LEFT;
+			});
+			
+			IntStream.range(parseTrees.getHeight(), d.supplierList.size() + parseTrees.getHeight()).forEach(i -> commKTableModel.setColumnWidth(i, 200));
+			IntStream.range(0, headRow).forEach(i -> commKTableModel.setRowHeight(i, 30));
+			
+			evaluationTableComposite.layout();
+			
+			columnWidth.clearBind();
+			columnWidth.bind(t -> {
+				IntStream.range(parseTrees.getHeight(), d.supplierList.size() + parseTrees.getHeight()).forEach(i -> commKTableModel.setColumnWidth(i, t));
+				resultKTable.redraw();
+			});
+			columnWidth.watch((o, n) -> {
+				if (n > o) IntStream.range(0, parseTrees.getLeafCount() + headRow).forEach(i -> {
+					int rowHeight = commKTableModel.getRowHeight(i);
+					rowHeight -= 20;
+					if (rowHeight < 30) rowHeight = 30;
+					commKTableModel.setRowHeight(i, rowHeight);
+				});
+			});
+			resultKTable.autoComputerColumnWidth();
+			this.minWidth = commKTableModel.getColumnWidth(commKTableModel.getFixedColumnCount());
+			columnWidth.set(minWidth);
+			
+			reviewContent.clearBind();
+			reviewContent.bind(t -> {
+				resultKTable.redraw(point.y, point.x, 1, 1);
+			});
+			
+		});
+		
+	}
+	
+	public void refresh(String tenderId, List<Supplier> supplierList, List<EvaluationFactor> factorList, List<SupplierEvaluationFactor> supplierEvaluationFactorList) {
+		TableData tableData = new TableData();
+		tableData.supplierList = Optional.ofNullable(supplierList).orElseGet(ArrayList::new);
+		tableData.factorList = Optional.ofNullable(factorList).orElseGet(ArrayList::new);
+		tableData.mapBySupplierIdByFactorCode = supplierEvaluationFactorList.stream().collect(CollectorUtils.groupingToMap(SupplierEvaluationFactor::getFactorCode, SupplierEvaluationFactor::getSupplierId));
+		this.tableData.set(tableData);
+	}
+	
+	public void refreshCell(String content) {
+		
+	}
+	
+	public void setTitleName(String titleName) {
+		this.titleName.set(titleName);
+	}
+	
+	public void addCellDoubleClickListeners(CellDoubleClickListener cellDoubleClickListener) {
+		this.cellDoubleClickListeners.add(cellDoubleClickListener);
+	}
+	
+	private void mounted() {
+		columnWidth.limit((o, n) -> {
+			if (o == minWidth || o == maxWidth) o = n;
+			if (o == minWidth) {
+				MessageDialog.openShortMessage("已到最小宽度!");
+				return false;
+			}
+			if (o == maxWidth) {
+				MessageDialog.openShortMessage("已到最大宽度!");
+				return false;
+			}
+			return true;
+		});
+	}
+	
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/TemplateTableComparisonComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/TemplateTableComparisonComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..39c32035010d8489ebdd129b8c1203b2cf75d409
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/TemplateTableComparisonComposite.java
@@ -0,0 +1,124 @@
+package com.gx.obe.struct.composite;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.OptionalInt;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.component.comparison.Column;
+import com.gx.obe.component.comparison.ComparisonData;
+import com.gx.obe.component.comparison.ComparisonTable;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.component.utils.CompositeUtils;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.components.core.vo.TableXML;
+import com.gx.obe.components.core.vo.Td;
+import com.gx.obe.components.core.vo.Tr;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.struct.beans.TemplateTable;
+import com.gx.obe.struct.service.TemplateTableService;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.util.utils.StringUtils;
+import com.gx.obe.web.entity.Supplier;
+
+public class TemplateTableComparisonComposite extends Composite {
+	
+	private final TemplateTableService templateTableService = new TemplateTableService();
+	
+	private final Prop<ComparisonData> comparisonData = new Prop<>();
+	
+	public TemplateTableComparisonComposite(Composite parent, int style) {
+		super(parent, style);
+		setLayout(new FillLayout(SWT.HORIZONTAL));
+		comparisonData.bind(t -> {
+			CompositeUtils.disposeChildren(this);
+			new ComparisonTable(this, t);
+			this.layout();
+		});
+	}
+	
+	public void refresh(String tenderId, String relChapterType, String dataCode, List<Supplier> supplierList) {
+		RxSwt.run(() -> getComparisonData(tenderId, relChapterType, dataCode, supplierList)).checkWidget(this).exe(comparisonData::set);
+	}
+	
+	private ComparisonData getComparisonData(String tenderId, String relChapterType, String dataCode, List<Supplier> supplierList) {
+		List<TemplateTable> templateTableList = templateTableService.getTemplateTableList(tenderId, relChapterType, dataCode);
+		if (CollectionUtils.isNull(templateTableList)) {
+			return null;
+		}
+		Map<String, TemplateTable> templateTableMap = templateTableList.stream().collect(Collectors.toMap(TemplateTable::getSupplierId, Function.identity()));
+		TemplateTable templateTable = templateTableMap.get(Constants.BIDDING_ID);
+		if (templateTable == null) {
+			return null;
+		}
+		TableXML tableXML = JsonUtil.jsonToBean(templateTable.getTableInfo(), TableXML.class);
+		if (tableXML == null) {
+			return null;
+		}
+		List<Tr> headList = tableXML.getHeadList();
+		if (headList.size() != 1) {
+			return null;
+		}
+		Tr head = headList.get(0);
+		OptionalInt indexCol = IntStream.range(0, head.getTds().length).filter(i -> "序号".equals(head.getTds()[i].getContent())).findAny();
+		if (!indexCol.isPresent()) {
+			return null;
+		}
+		ComparisonData comparisonData = new ComparisonData();
+		tableXML.getBodyList().forEach(body -> Optional.ofNullable(getContent(body, indexCol.getAsInt())).filter(StringUtils::isNotEmpty).ifPresent(comparisonData::addRow));
+		
+		supplierList.forEach(supplier -> {
+			comparisonData.addTitleCol(new Column(supplier.getId(), supplier.getSupplierName()));
+		});
+		
+		IntStream.range(0, head.getTds().length).forEach(i -> {
+			comparisonDataInit(templateTableMap, tableXML, head, indexCol.getAsInt(), i, supplierList, comparisonData);
+		});
+		return comparisonData;
+	}
+	
+	private void comparisonDataInit(Map<String, TemplateTable> templateTableMap, TableXML tableXML, Tr head, int indexCol, int col, List<Supplier> supplierList, ComparisonData comparisonData) {
+		Td td = head.getTds()[col];
+		if (td.isNeedFill()) {
+			comparisonData.addItemCol(new Column(col + "", td.getContent()));
+			supplierList.forEach(supplier -> {
+				supplierComparisonDataInit(templateTableMap, indexCol, col, supplier, comparisonData);
+			});
+		} else {
+			comparisonData.addHeadCol(new Column(col + "", td.getContent()));
+			tableXML.getBodyList().forEach(body -> {
+				comparisonData.putHeadContent(getContent(body, indexCol), col + "", getContent(body, col));
+			});
+		}
+	}
+	
+	private void supplierComparisonDataInit(Map<String, TemplateTable> templateTableMap, int indexCol, int col, Supplier supplier, ComparisonData comparisonData) {
+		TemplateTable supplierTemplateTable = templateTableMap.get(supplier.getId());
+		if (supplierTemplateTable == null) {
+			return;
+		}
+		TableXML supplierTableXML = JsonUtil.jsonToBean(supplierTemplateTable.getTableInfo(), TableXML.class);
+		if (supplierTableXML == null) {
+			return;
+		}
+		supplierTableXML.getBodyList().forEach(body -> {
+			comparisonData.putComparisonContent(getContent(body, indexCol), supplier.getId(), col + "", getContent(body, col));
+		});
+	}
+	
+	private String getContent(Tr tr, int col) {
+		return tr.getTds()[col].getContent();
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/composite/TemplateTableListComposite.java b/com.gx.obe.struct/src/com/gx/obe/struct/composite/TemplateTableListComposite.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b95703359837acc323856969c93be98635ca328
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/composite/TemplateTableListComposite.java
@@ -0,0 +1,125 @@
+package com.gx.obe.struct.composite;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.widgets.ESepator;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.common.widget.button.RectangleRadioButton;
+import com.gx.obe.component.handler.TabHandler;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.struct.enums.DataCategoryEnum;
+import com.gx.obe.struct.service.EvaluationContentService;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.evaluation.EvaluationContent;
+import com.swtdesigner.SWTResourceManager;
+
+public class TemplateTableListComposite extends Composite {
+	
+	private final EvaluationContentService evaluationContentService = new EvaluationContentService();
+	
+	private final Prop<TemplateTableData> templateTableData = new Prop<>();
+	
+	private class TemplateTableData {
+		private String tenderId;
+		private List<EvaluationContent> evaluationContentList;
+		private List<Supplier> supplierList;
+	}
+	
+	private final Prop<TemplateTableComparisonData> templateTableComparisonData = new Prop<>();
+	
+	private class TemplateTableComparisonData {
+		private String tenderId;
+		private String relChapterType;
+		private String dataCode;
+		private List<Supplier> supplierList;
+	}
+	
+	public TemplateTableListComposite(Composite parent, int style) {
+		super(parent, style);
+		setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		setBackgroundMode(SWT.INHERIT_FORCE);
+		
+		StackLayout stackLayout = new StackLayout();
+		setLayout(stackLayout);
+		Consumer<Control> topControlConsumer = t -> {
+			stackLayout.topControl = t;
+			this.layout();
+		};
+		
+		Composite composite_1 = new Composite(this, SWT.NONE);
+		composite_1.setLayout(new GridLayout(1, false));
+		
+		Label label = new Label(composite_1, SWT.WRAP);
+		label.setForeground(SWTResourceManager.getColor(200, 200, 200));
+		label.setFont(SWTResourceManager.getFont("宋体", 20, SWT.BOLD));
+		label.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true, 1, 1));
+		label.setText("当前指标未绑定小范本表格评审点!");
+		
+		Composite composite = new Composite(this, SWT.NONE);
+		GridLayout gl_composite = new GridLayout(1, false);
+		gl_composite.verticalSpacing = 0;
+		gl_composite.marginHeight = 0;
+		gl_composite.marginWidth = 0;
+		composite.setLayout(gl_composite);
+		
+		Composite tabComposite = new Composite(composite, SWT.NONE);
+		RowLayout rl_tabComposite = new RowLayout(SWT.HORIZONTAL);
+		rl_tabComposite.marginBottom = 0;
+		tabComposite.setLayout(rl_tabComposite);
+		tabComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		TabHandler<RectangleRadioButton> handler = new TabHandler<>(tabComposite, t -> new RectangleRadioButton(t, SWT.NONE));
+		
+		this.templateTableData.bind(d -> {
+			if (d.evaluationContentList.isEmpty()) {
+				topControlConsumer.accept(composite_1);
+			} else {
+				topControlConsumer.accept(composite);
+				handler.start().listHand(d.evaluationContentList, EvaluationContent::getEvalPointName, t -> selectAction(d.tenderId, t, d.supplierList)).end();
+			}
+		});
+		
+		ESepator label_1 = new ESepator(composite, SWT.HORIZONTAL);
+		label_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		label_1.setBackground(ColorConstants.SKIN_BG);
+		
+		TemplateTableComparisonComposite comparisonComposite = new TemplateTableComparisonComposite(composite, SWT.NONE);
+		comparisonComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		this.templateTableComparisonData.bind(d -> comparisonComposite.refresh(d.tenderId, d.relChapterType, d.dataCode, d.supplierList));
+	}
+	
+	private void selectAction(String tenderId, EvaluationContent evaluationContent, List<Supplier> supplierList) {
+		TemplateTableComparisonData data = new TemplateTableComparisonData();
+		data.tenderId = tenderId;
+		data.relChapterType = evaluationContent.getRelChapterType();
+		data.dataCode = evaluationContent.getDataCode();
+		data.supplierList = supplierList;
+		this.templateTableComparisonData.set(data);
+	}
+	
+	public void refresh(String tenderId, String factorCode, List<Supplier> supplierList) {
+		RxSwt.run(() -> evaluationContentService.getEvaluationContentListByFactorCode(tenderId, factorCode)).checkWidget(this).other(ArrayList::new).exe(l -> {
+			TemplateTableData data = new TemplateTableData();
+			data.tenderId = tenderId;
+			data.evaluationContentList = l.stream().filter(t -> DataCategoryEnum.TT.getKey().equals(t.getDataCategory())).collect(Collectors.toList());
+			data.supplierList = supplierList;
+			this.templateTableData.set(data);
+		});
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/dialog/AuxevaluationFullScreenDialog.java b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/AuxevaluationFullScreenDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..d40841011d3bd378ced6abf2758fbe9cf1c8bafc
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/AuxevaluationFullScreenDialog.java
@@ -0,0 +1,49 @@
+package com.gx.obe.struct.dialog;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.core.utils.SwtUtils;
+import org.eclipse.swt.core.widgets.EDialog;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+import com.gx.obe.components.core.Constants;
+
+public class AuxevaluationFullScreenDialog extends EDialog {
+	
+	private String stageId;
+	private String token;
+	
+	public AuxevaluationFullScreenDialog(Shell parentShell, String stageId, String token) {
+		super(parentShell);
+		this.setTitle("辅助评标");
+		this.stageId = stageId;
+		this.token = token;
+	}
+	
+	@Override
+	protected Control createDialogArea(Composite parent) {
+		Composite container = (Composite) super.createDialogArea(parent);
+		container.setLayout(new FillLayout(SWT.HORIZONTAL));
+		
+		Browser browser = new Browser(container, SWT.NONE);
+//		browser.setUrl("http://dtjg.cse-bidding.com/bidweb/#/auxevaluationFullScreen/projectInfo?stageId=" + stageId);
+		browser.setUrl(Constants.getAuxiliaryPlatformUrl("bidweb/#/auxevaluationFullScreen/projectInfo") + "?stageId=" + stageId + "&token=" + token + "&sourceType=dt");
+		return container;
+	}
+	
+	@Override
+	protected Point getInitialSize() {
+		return new Point(1502, 950);
+	}
+	
+	@Override
+	protected void initializeBounds() {
+		super.initializeBounds();
+		SwtUtils.setCenter(getShell());
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/dialog/EditOpinionShell.java b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/EditOpinionShell.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc634238cab3d07a173dede2e441d442e5d18165
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/EditOpinionShell.java
@@ -0,0 +1,429 @@
+package com.gx.obe.struct.dialog;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.core.widgets.ELink;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.common.icons.IconsActivator;
+import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.struct.beans.AbsoluteModelDO;
+import com.gx.obe.struct.beans.IntelligentEvalDO;
+import com.gx.obe.struct.beans.LiftRateDO;
+import com.gx.obe.struct.beans.ScoreOptionsDO;
+import com.gx.obe.struct.beans.SelfEvalParamsDO;
+import com.gx.obe.struct.listener.EditOpinionListener;
+import com.gx.obe.util.utils.BigDecimalUtils;
+import com.gx.obe.util.utils.ObjectUtils;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.swtdesigner.ResourceManager;
+import com.swtdesigner.SWTResourceManager;
+
+public class EditOpinionShell extends Shell {
+	private Listener deactivateListener;
+	private EvaluationFactor curFactor;
+	private SupplierEvaluationFactor supplierEvaluationFactor;
+	private IntelligentEvalDO intelligentEvalDO;
+	private EditOpinionListener editOpinionListener;
+	private ELink editOpinionLink;
+	private ELink saveEditOpinionLink;
+	private String editOpinionStr = null;
+	private String editOpinionValueStr = null;
+	private Composite editContentComposite;
+	private Text reasonText;
+	private GridData gd_editContentComposite;
+	private GridLayout gl_editContentComposite;
+
+
+	/**
+	 * Create the shell.
+	 * @param display
+	 */
+	public EditOpinionShell(Shell shell, EvaluationFactor curFactor, SupplierEvaluationFactor supplierEvaluationFactor, EditOpinionListener editOpinionListener) {
+		super(shell, SWT.NO_TRIM);
+		setBackground(ColorConstants.BORDER_LINE_COLOR);
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.verticalSpacing = 1;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		this.curFactor = curFactor;
+		this.supplierEvaluationFactor = supplierEvaluationFactor;
+		this.editOpinionListener = editOpinionListener;
+		addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				removeListener(SWT.Deactivate, deactivateListener);
+			}
+		});
+		
+		editContentComposite = new Composite(this, SWT.NONE);
+		editContentComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		editContentComposite.setBackgroundMode(SWT.INHERIT_FORCE);
+		
+		gd_editContentComposite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		editContentComposite.setLayoutData(gd_editContentComposite);
+		gl_editContentComposite = new GridLayout(1, false);
+		gl_editContentComposite.marginHeight = 1;
+		gl_editContentComposite.marginWidth = 1;
+		editContentComposite.setLayout(gl_editContentComposite);;
+		
+		Composite reasonTitleComposite = new Composite(this, SWT.NONE);
+		reasonTitleComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		reasonTitleComposite.setBackgroundMode(SWT.INHERIT_FORCE);
+		reasonTitleComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
+		reasonTitleComposite.setLayout(new GridLayout(1, false));
+		
+		Label reasonLabel = new Label(reasonTitleComposite, SWT.NONE);
+		reasonLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1));
+		reasonLabel.setText("修改原因:");
+		
+		Composite editReasonComposite = new Composite(this, SWT.NONE);
+		editReasonComposite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		editReasonComposite.setBackgroundMode(SWT.INHERIT_FORCE);
+		GridData gd_editReasonComposite = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+		gd_editReasonComposite.heightHint = 40;
+		editReasonComposite.setLayoutData(gd_editReasonComposite);
+		GridLayout gl_editReasonComposite = new GridLayout(3, false);
+		gl_editReasonComposite.horizontalSpacing = 0;
+		gl_editReasonComposite.marginHeight = 0;
+		gl_editReasonComposite.marginWidth = 0;
+		editReasonComposite.setLayout(gl_editReasonComposite);
+		
+		
+		reasonText = new Text(editReasonComposite, SWT.WRAP | SWT.V_SCROLL);
+		reasonText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 2));
+		reasonText.setTextLimit(200);
+		reasonText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent arg0) {
+			}
+		});
+		
+		saveEditOpinionLink = new ELink(editReasonComposite, SWT.NONE);
+		saveEditOpinionLink.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, false, true, 2, 1));
+		saveEditOpinionLink.setText("确认修改");
+		saveEditOpinionLink.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/save.png"));
+		saveEditOpinionLink.addMouseListener(new MouseAdapter() {
+			public void mouseUp(MouseEvent e) {
+				saveEditOpinionAction();
+			}
+		});;
+		
+		editOpinionLink = new ELink(editReasonComposite, SWT.NONE);
+		editOpinionLink.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 2, 1));
+		editOpinionLink.setText("取消修改");
+		editOpinionLink.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/back.png"));
+		editOpinionLink.addMouseListener(new MouseAdapter() {
+			public void mouseUp(MouseEvent e) {
+				cancleAction();
+			}
+		});
+		createContents();
+		init();
+	}
+	
+	private void init() {
+		deactivateListener = new Listener(){
+			@Override
+			public void handleEvent(Event arg0) {
+				close();
+			}
+		};
+		
+		addListener(SWT.Deactivate, deactivateListener);
+		editOpinionStr = supplierEvaluationFactor.getOpinion();
+		reasonText.setText(ObjectUtils.getObjString(supplierEvaluationFactor.getModifyReason()));
+		// 如果是智能评审类型
+		if(EvaluationFactorEnum.SCORE_TYPE_AI.equals(curFactor.getScoreType())) {
+			intelligentEvalDO = JsonUtil.jsonToBean(curFactor.getIntelligentEval(), IntelligentEvalDO.class);
+		}
+		if(null != intelligentEvalDO) {
+			if("F".equals(intelligentEvalDO.getFactorModel())) {
+				addComboOpinion();
+			}else  if("B".equals(intelligentEvalDO.getFactorModel())) {
+				addLiftRateOpinion();
+			} else if("G".equals(intelligentEvalDO.getFactorModel())) {
+				addAbsoluteParamOpinion();
+			}else {
+				addStringOpinion();
+			}
+		}
+		else {
+			addStringOpinion();
+		}
+	}
+	
+	/**
+	 * 确认修改
+	 */
+	private void saveEditOpinionAction() {
+		removeListener(SWT.Deactivate, deactivateListener);
+		if(null != intelligentEvalDO) {
+			SelfEvalParamsDO selfEvalParamsDO = JsonUtil.jsonToBean(supplierEvaluationFactor.getParamValues(), SelfEvalParamsDO.class);
+			if("F".equals(intelligentEvalDO.getFactorModel())) {
+				if(null != supplierEvaluationFactor.getParamValues()) {
+					if(null != selfEvalParamsDO) {
+						selfEvalParamsDO.setSelectParamValue(editOpinionValueStr);
+						supplierEvaluationFactor.setParamValues(selfEvalParamsDO.toJson());
+					}
+				}
+			}else if("G".equals(intelligentEvalDO.getFactorModel())) {
+				 Pattern p = Pattern.compile("^\\d*[1-9]\\d*$");   
+				 Matcher m = p.matcher(editOpinionValueStr);   
+				if(!m.matches()){
+					MessageDialog.openShortMessage("请输入正确的整数绝对值!");
+					addListener(SWT.Deactivate, deactivateListener);
+					return ;
+				}
+				if(null != selfEvalParamsDO) {
+					selfEvalParamsDO.setSelectParamValue(editOpinionValueStr);
+					supplierEvaluationFactor.setParamValues(selfEvalParamsDO.toJson());
+				}
+			}else if("B".equals(intelligentEvalDO.getFactorModel())) {
+				
+				BigDecimal value = null;
+				try {
+					value = new BigDecimal(editOpinionValueStr);
+					LiftRateDO liftRateDO = intelligentEvalDO.getLiftRate();
+					if(null != liftRateDO) {
+						editOpinionValueStr = BigDecimalUtils.round(value, ObjectUtils.getIntValue(liftRateDO.getDecimalDigits(), 6)).toString();
+						editOpinionStr = editOpinionValueStr + liftRateDO.getUnit();
+					}
+				} catch (Exception e) {
+					MessageDialog.openShortMessage("请输入正确的数值!");
+					addListener(SWT.Deactivate, deactivateListener);
+					return ;
+				}
+				if(null != selfEvalParamsDO) {
+					selfEvalParamsDO.setSelectParamValue(editOpinionValueStr);
+					supplierEvaluationFactor.setParamValues(selfEvalParamsDO.toJson());
+				}
+			}
+		}
+		if(reasonText.getText().trim().length() == 0) {
+			MessageDialog.openShortMessage("请输入修改原因!");
+			addListener(SWT.Deactivate, deactivateListener);
+			return;
+		}
+		supplierEvaluationFactor.setModifyReason(reasonText.getText());
+		editOpinionListener.editOpinion(editOpinionStr, reasonText.getText());
+		this.close();
+	}
+	
+	/**
+	 * 取消修改
+	 */
+	private void cancleAction() {
+		this.close();
+	}
+	
+	private void addStringOpinion() {
+		gl_editContentComposite.numColumns = 1;
+    	gd_editContentComposite.grabExcessVerticalSpace = true;
+		gd_editContentComposite.heightHint = 60;
+		
+		final Text opinionText = new Text(editContentComposite, SWT.WRAP | SWT.V_SCROLL);
+		opinionText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		opinionText.setText(ObjectUtils.getObjString(supplierEvaluationFactor.getOpinion()));
+		opinionText.setTextLimit(2000);
+		editOpinionStr = opinionText.getText();
+		opinionText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent arg0) {
+				editOpinionStr = opinionText.getText().trim();
+			}
+		});
+		editContentComposite.getParent().layout();
+	}
+
+    /**
+     * 设置下拉选项评议意见
+     */
+    private void addComboOpinion() {
+    	gl_editContentComposite.numColumns = 1;
+    	gd_editContentComposite.grabExcessVerticalSpace = false;
+    	gd_editContentComposite.heightHint = -1;
+    	 final Combo opinionCombo = new Combo(editContentComposite, SWT.READ_ONLY);
+    	 opinionCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+    	 opinionCombo.addSelectionListener(new SelectionAdapter() {
+    		 public void widgetSelected(SelectionEvent e) {
+    			 selectOpinionAction(opinionCombo);
+    		 }
+    	 });
+    	 
+    	 String selectParamValue = null;// 下拉选项的值
+		   if(null != supplierEvaluationFactor.getParamValues()) {
+			   SelfEvalParamsDO selfEvalParamsDO = JsonUtil.jsonToBean(supplierEvaluationFactor.getParamValues(), SelfEvalParamsDO.class);
+			   if(null != selfEvalParamsDO) {
+				   selectParamValue = selfEvalParamsDO.getSelectParamValue();
+				   editOpinionValueStr = selectParamValue;
+			   }
+		   }
+		   
+    	 int index = 0;
+    	 List<ScoreOptionsDO> scoreOptionsDOList = intelligentEvalDO.getScoreOptionsDOList(); 
+    	 if(null != scoreOptionsDOList) {
+    		 for(ScoreOptionsDO scoreOptionsDO : scoreOptionsDOList) {
+    			 opinionCombo.add(scoreOptionsDO.getName(), index);
+    			 opinionCombo.setData(index + "", scoreOptionsDO);
+    			 if(null != selectParamValue) {
+    				 // 如果有下拉选项值,则通过值进行匹配
+    				 if(selectParamValue.equals(scoreOptionsDO.getScoreItemId())){
+    					 opinionCombo.select(index);
+    				 }
+    			 }else {
+    				 if(scoreOptionsDO.getName().equals(supplierEvaluationFactor.getOpinion())){
+    					 opinionCombo.select(index);
+    				 }
+    			 }
+    			 index++;
+    		 }
+    	 }
+    	 
+    }
+    /**
+     * @Description: 修改下拉框评审意见
+     * @author chenxw
+     */
+    private void selectOpinionAction(Combo opinionCombo) {
+    	if(opinionCombo.getSelectionIndex() >= 0 && null != curFactor) {
+    		if(null != supplierEvaluationFactor) {
+    			ScoreOptionsDO scoreOptionsDO = (ScoreOptionsDO)opinionCombo.getData("" + opinionCombo.getSelectionIndex());
+    			if(null != scoreOptionsDO) {
+    				editOpinionStr = scoreOptionsDO.getName();
+    				editOpinionValueStr = scoreOptionsDO.getScoreItemId();
+    			}
+    		}
+    	}
+    }
+    
+    /**
+     * 绝对值模型修改
+     */
+    private void addAbsoluteParamOpinion() {
+    	gl_editContentComposite.numColumns = 3;
+    	gd_editContentComposite.grabExcessVerticalSpace = false;
+		gd_editContentComposite.heightHint = -1;
+		
+		String selectParamValue = null;// 下拉选项的值
+		if(null != supplierEvaluationFactor.getParamValues()) {
+			SelfEvalParamsDO selfEvalParamsDO = JsonUtil.jsonToBean(supplierEvaluationFactor.getParamValues(), SelfEvalParamsDO.class);
+			if(null != selfEvalParamsDO) {
+				selectParamValue = selfEvalParamsDO.getSelectParamValue();
+				editOpinionValueStr = selectParamValue;
+			}
+		}
+		AbsoluteModelDO absoluteModelDO = intelligentEvalDO.getAbsoluteModelDO();
+		
+    	final Text opinionText = new Text(editContentComposite, SWT.CENTER | SWT.BORDER);
+		GridData gd_opinionText = new GridData(SWT.FILL, SWT.FILL, false, true, 1, 1);
+		gd_opinionText.widthHint = 50;
+		opinionText.setLayoutData(gd_opinionText);
+		opinionText.setText(ObjectUtils.getObjString(selectParamValue));
+		opinionText.setTextLimit(2000);
+		Label unitLabel = new Label(editContentComposite, SWT.NONE);
+		unitLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 1, 1));
+		if(null != absoluteModelDO) {
+			unitLabel.setText(ObjectUtils.getObjString(absoluteModelDO.getAbsoluteUnit(),"未知单位"));
+		}
+		
+    	Label tipsLabel = new Label(editContentComposite, SWT.NONE);
+    	tipsLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+    	tipsLabel.setForeground(ColorConstants.NOTE_TIPS_COLOR);
+    	//<bidFillMemo><![CDATA[此处只能填写整数绝对值]]></bidFillMemo>
+    	tipsLabel.setText("请填写整数绝对值!");
+    	
+    	opinionText.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent arg0) {
+				editOpinionStr = opinionText.getText().trim() + unitLabel.getText();
+				editOpinionValueStr = opinionText.getText().trim();
+			}
+		});
+    	
+    }
+    /**
+     * 升降率模型修改
+     */
+    private void addLiftRateOpinion() {
+    	gl_editContentComposite.numColumns = 3;
+    	gd_editContentComposite.grabExcessVerticalSpace = false;
+    	gd_editContentComposite.heightHint = -1;
+    	
+    	String selectParamValue = null;// 下拉选项的值
+    	if(null != supplierEvaluationFactor.getParamValues()) {
+    		SelfEvalParamsDO selfEvalParamsDO = JsonUtil.jsonToBean(supplierEvaluationFactor.getParamValues(), SelfEvalParamsDO.class);
+    		if(null != selfEvalParamsDO) {
+    			selectParamValue = selfEvalParamsDO.getSelectParamValue();
+    			editOpinionValueStr = selectParamValue;
+    		}
+    	}
+    	
+    	LiftRateDO liftRateDO = intelligentEvalDO.getLiftRate();
+    	
+    	final Text opinionText = new Text(editContentComposite, SWT.CENTER | SWT.BORDER);
+    	GridData gd_opinionText = new GridData(SWT.FILL, SWT.FILL, false, true, 1, 1);
+    	gd_opinionText.widthHint = 100;
+    	opinionText.setLayoutData(gd_opinionText);
+//    	<unit>%</unit>
+//        <decimalDigits>6</decimalDigits>
+    	opinionText.setText(ObjectUtils.getObjString(selectParamValue));
+    	opinionText.setTextLimit(2000);
+    	Label unitLabel = new Label(editContentComposite, SWT.NONE);
+    	unitLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true, 1, 1));
+    	if(null != liftRateDO) {
+    		unitLabel.setText(ObjectUtils.getObjString(liftRateDO.getUnit(),"未知单位"));
+    	}
+    	
+    	Label tipsLabel = new Label(editContentComposite, SWT.NONE);
+    	tipsLabel.setForeground(ColorConstants.NOTE_TIPS_COLOR);
+    	tipsLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+    	//<bidFillMemo><![CDATA[此处应填写数值,小数点保留6位]]></bidFillMemo>
+    	tipsLabel.setText("请填写数值(小数点保留"+liftRateDO.getDecimalDigits()+"位)!");
+    	
+    	opinionText.addModifyListener(new ModifyListener() {
+    		public void modifyText(ModifyEvent arg0) {
+    			editOpinionStr = opinionText.getText().trim() + unitLabel.getText();
+    			editOpinionValueStr = opinionText.getText().trim();
+    		}
+    	});
+    	
+    }
+   
+
+	/**
+	 * Create contents of the shell.
+	 */
+	protected void createContents() {
+		setText("SWT Application");
+		setSize(450, 300);
+
+	}
+
+	@Override
+	protected void checkSubclass() {
+		// Disable the check that prevents subclassing of SWT components
+	}
+
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/dialog/FactorClearBidStepDialog.java b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/FactorClearBidStepDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..229e9cc3882d12268c3ccae0aece49ba949df240
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/FactorClearBidStepDialog.java
@@ -0,0 +1,169 @@
+package com.gx.obe.struct.dialog;
+
+import java.text.MessageFormat;
+import java.util.Optional;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.utils.WidgetUtils;
+import org.eclipse.swt.core.widgets.ELink;
+import org.eclipse.swt.core.widgets.ESepator;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.common.icons.IconsActivator;
+import com.gx.obe.common.widget.button.ImageRaido;
+import com.gx.obe.component.handler.RaidoHandler;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+import com.gx.obe.message.Messages;
+import com.gx.obe.step.dialog.EvaluationStepDialog;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.entity.expert.Expert;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.service.expert.ExpertService;
+import com.swtdesigner.ResourceManager;
+import com.swtdesigner.SWTResourceManager;
+
+public class FactorClearBidStepDialog extends EvaluationStepDialog {
+	
+	private final ExpertService expertService = new ExpertService();
+	
+	private final Prop<EvaluationFactorTypeEnum> evaluationFactorTypeEnum = new Prop<>();
+	
+	private final Prop<Expert> expert = new Prop<>();
+	
+	public FactorClearBidStepDialog(Shell parentShell, TenderProjectEntity tenderProject, EvaluationStep evaluationStep) {
+		super(parentShell, tenderProject, evaluationStep);
+	}
+	
+	@Override
+	protected void createFromArea(Composite fromComposite, Composite gridComposite) {
+		evaluationFactorTypeEnum.bind(t -> {
+			switch (t) {
+				case COMPLIANCE:
+					setStepNameText("符合性指标评议");
+					break;
+				case BUSINESS:
+					setStepNameText("商务指标评议");
+					break;
+				case TECHNOLOGY:
+					setStepNameText("技术指标评议");
+					break;
+			}
+		});
+		evaluationFactorTypeEnum.bind(t -> expert.set(null));
+		
+		CLabel label = new CLabel(fromComposite, SWT.NONE);
+		label.setFont(SWTResourceManager.getFont("微软雅黑", 9, SWT.NORMAL));
+		label.setAlignment(SWT.RIGHT);
+		label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
+		label.setText("评议类型:");
+		
+		Composite composite = new Composite(fromComposite, SWT.NONE);
+		composite.setLayout(new GridLayout(2, false));
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
+		
+		Composite composite_1 = new Composite(composite, SWT.NONE);
+		composite_1.setLayout(new GridLayout(3, false));
+		
+		RaidoHandler<ImageRaido, EvaluationFactorTypeEnum> raidoHandler = new RaidoHandler<>(composite_1, p -> {
+			ImageRaido imageRaido = new ImageRaido(p, SWT.NONE);
+			imageRaido.setFont(SWTResourceManager.getFont("微软雅黑", 10, SWT.NORMAL));
+			imageRaido.setImageSize(24);
+			return imageRaido;
+		});
+		raidoHandler.start().hand(EvaluationFactorTypeEnum.COMPLIANCE, "符合性评议").hand(EvaluationFactorTypeEnum.BUSINESS, "商务评议").hand(EvaluationFactorTypeEnum.TECHNOLOGY, "技术评议").end();
+		evaluationFactorTypeEnum.bindBidirectional(raidoHandler);
+		
+		Composite composite_2 = new Composite(composite, SWT.NONE);
+		GridLayout gl_composite_2 = new GridLayout(2, false);
+		composite_2.setLayout(gl_composite_2);
+		evaluationFactorTypeEnum.bindExe(t -> {
+			WidgetUtils.setControlVisible(composite_2, t != null);
+			composite_2.getParent().layout();
+		});
+		
+		Composite composite_3 = new Composite(composite_2, SWT.NONE);
+		composite_3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
+		GridLayout gl_composite_3 = new GridLayout(1, false);
+		gl_composite_3.verticalSpacing = 0;
+		gl_composite_3.marginHeight = 0;
+		gl_composite_3.marginWidth = 0;
+		composite_3.setLayout(gl_composite_3);
+		
+		CLabel lblNewLabel = new CLabel(composite_3, SWT.NONE);
+		lblNewLabel.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false, 1, 1));
+		expert.bind(t -> {
+			lblNewLabel.setText(Optional.ofNullable(t).map(Expert::getUserName).orElse(""));
+			lblNewLabel.getParent().layout();
+		});
+		
+		ESepator label_1 = new ESepator(composite_3, SWT.HORIZONTAL);
+		GridData gd_label_1 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
+		gd_label_1.widthHint = 100;
+		label_1.setLayoutData(gd_label_1);
+		label_1.setBackground(ColorConstants.SEP_LIGHT_COLOR);
+		
+		ELink select_expert = new ELink(composite_2, SWT.NONE);
+		select_expert.addMouseListener(MouseListener.mouseUpAdapter($ -> selectExpert()));
+		select_expert.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/search.png"));
+		select_expert.setLayoutData(new GridData(SWT.LEFT, SWT.BOTTOM, false, true, 1, 1));
+		select_expert.setText(MessageFormat.format(Messages.Button_selectFormat, Messages.Expert));
+	}
+	
+	private void selectExpert() {
+		SelectStepExpertDialog.selectExpert(getShell(), tenderProject.getId(), evaluationFactorTypeEnum.get()).thenThrow(expert::set);
+	}
+	
+	@Override
+	protected void setFromData(EvaluationStep evaluationStep) {
+		evaluationFactorTypeEnum.set(EvaluationFactorTypeEnum.MAP.get(evaluationStep.getEvaluationParamByKey(EvaluationStepEnum.EVALUATION_FACTOR_TYPE)));
+		RxSwt.run(() -> expertService.getEvaluationStepExpertList(tenderProject.getId(), evaluationStep)).checkWidget(getShell()).exe(t -> {
+			if (CollectionUtils.isNotNull(t)) expert.set(t.get(0));
+		});
+	}
+	
+	@Override
+	protected String valFromData() {
+		if (evaluationFactorTypeEnum.get() == null) return "请选择评审类型!";
+		if (expert.get() == null) return "请选择评审专家!";
+		return super.valFromData();
+	}
+	
+	@Override
+	protected void getFromData(EvaluationStep evaluationStep) {
+		evaluationStep.setEvaluationParam(EvaluationStepEnum.EVALUATION_FACTOR_TYPE, evaluationFactorTypeEnum.get().getKey());
+		evaluationStep.setRoleType(EvaluationStepEnum.CUSTOM);
+		addStepExpertUserId(expert.get().getUserId());
+	}
+	
+	@Override
+	protected String getTipsText() {
+		return "评审专家通过对供应商标书及结构化数据进行分析后对每一下评审指标录入评审意见!";
+	}
+	
+	@Override
+	protected String getStepNameDef() {
+		return "指标评议";
+	}
+	
+	@Override
+	protected String getStepType() {
+		return EvaluationStepEnum.FACTOR_CLEAR_BID;
+	}
+	
+	@Override
+	protected Point getInitialSize() {
+		return new Point(600, 400);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/dialog/SelectStepExpertDialog.java b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/SelectStepExpertDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cb321f073f8446d9e5407f8a5d1ef1197ef5b13
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/dialog/SelectStepExpertDialog.java
@@ -0,0 +1,167 @@
+package com.gx.obe.struct.dialog;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.widgets.EButton;
+import org.eclipse.swt.core.widgets.EDialog;
+import org.eclipse.swt.custom.CLabel;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+
+import com.gx.obe.ColorConstants;
+import com.gx.obe.bind.promise.Promise;
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.bind.prop.RProp;
+import com.gx.obe.common.icons.IconsActivator;
+import com.gx.obe.component.grid.FGrid;
+import com.gx.obe.component.listener.SelectionListener;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.components.core.enumeration.ExpertEnum;
+import com.gx.obe.message.Messages;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.web.entity.expert.Expert;
+import com.gx.obe.web.service.expert.ExpertService;
+import com.swtdesigner.ResourceManager;
+import com.swtdesigner.SWTResourceManager;
+
+public class SelectStepExpertDialog extends EDialog {
+	
+	private final List<SelectionListener<Expert>> selectionListeners = new ArrayList<>();
+	
+	private final ExpertService expertService = new ExpertService();
+	
+	private final String tenderId;
+	private final EvaluationFactorTypeEnum evaluationFactorTypeEnum;
+	
+	private Prop<List<Expert>> expertList = new Prop<>();
+	private RProp<Expert> expert = new RProp<>();
+	
+	public SelectStepExpertDialog(Shell parentShell, String tenderId, EvaluationFactorTypeEnum evaluationFactorTypeEnum) {
+		super(parentShell);
+		this.tenderId = tenderId;
+		this.evaluationFactorTypeEnum = evaluationFactorTypeEnum;
+		setTitle("选择评标专家");
+	}
+	
+	@Override
+	protected Control createDialogArea(Composite parent) {
+		Composite container = (Composite) super.createDialogArea(parent);
+		container.setBackground(ColorConstants.BORDER_LINE_COLOR);
+		GridLayout gl_container = new GridLayout(1, false);
+		gl_container.horizontalSpacing = 0;
+		gl_container.verticalSpacing = 1;
+		gl_container.marginHeight = 0;
+		gl_container.marginWidth = 0;
+		container.setLayout(gl_container);
+		
+		Composite composite_1 = new Composite(container, SWT.NONE);
+		composite_1.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		composite_1.setLayout(new GridLayout(1, false));
+		composite_1.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		composite_1.setBackgroundMode(SWT.INHERIT_FORCE);
+		
+		CLabel label_3 = new CLabel(composite_1, SWT.NONE);
+		label_3.setFont(SWTResourceManager.getFont("宋体", 10, SWT.BOLD));
+		label_3.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/television.png"));
+		label_3.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		label_3.setText(Messages.EvalExpert);
+		
+		Composite composite_2 = new Composite(container, SWT.NONE);
+		composite_2.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		composite_2.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		GridLayout gl_composite_2 = new GridLayout(1, false);
+		gl_composite_2.marginHeight = 0;
+		gl_composite_2.marginWidth = 0;
+		composite_2.setLayout(gl_composite_2);
+		
+		FGrid<Expert> composite_3 = new FGrid<>(composite_2);
+		composite_3.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
+		composite_3.addIndexColumn(Messages.Num).setWidth(50);
+		composite_3.addColumn(Messages.FullName, t -> t.getUser().getUserName(), SWT.CENTER).setWidth(100);
+		composite_3.addColumn(Messages.Account, t -> t.getUser().getUserAccount(), SWT.CENTER).setWidth(100);
+		composite_3.addColumn(Messages.ExpertType, Expert::getExpertTypeAndRole, SWT.CENTER).setWidth(250);
+		expertList.bind(composite_3::refresh);
+		expert.reader(composite_3);
+		
+		Composite composite = new Composite(container, SWT.NONE);
+		composite.setBackground(SWTResourceManager.getColor(SWT.COLOR_WHITE));
+		composite.setBackgroundMode(SWT.INHERIT_FORCE);
+		composite.setLayout(new GridLayout(2, false));
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		
+		EButton button_1 = new EButton(composite, SWT.NONE);
+		button_1.addMouseListener(MouseListener.mouseUpAdapter($ -> confirmAction()));
+		button_1.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/yes.png"));
+		button_1.setText(Messages.Button_ok);
+		button_1.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false, 1, 1));
+		
+		EButton button = new EButton(composite, SWT.NONE);
+		button.addMouseListener(MouseListener.mouseUpAdapter($ -> close()));
+		button.setImage(ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/close.png"));
+		button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1));
+		button.setText(Messages.Button_close);
+		
+		init();
+		
+		return container;
+	}
+	
+	private void init() {
+		RxSwt.run(this::queryExpertList).checkWidget(getShell()).exe(expertList::set);
+	}
+	
+	public List<Expert> queryExpertList() {
+		List<Expert> experts = expertService.getExpertList(tenderId, ExpertEnum.ALL);
+		if (experts == null) {
+			return null;
+		}
+		return experts.stream().filter(getExpertPredicate()).collect(Collectors.toList());
+	}
+	
+	private Predicate<Expert> getExpertPredicate() {
+		switch (evaluationFactorTypeEnum) {
+			case COMPLIANCE:
+				return t -> true;
+			case BUSINESS:
+				return t -> (t.getEvalBidTypeNotNull() & ExpertEnum.EXPERT_BUS) != 0;
+			case TECHNOLOGY:
+				return t -> (t.getEvalBidTypeNotNull() & ExpertEnum.EXPERT_TEC) != 0;
+			default:
+				return t -> false;
+		}
+	}
+	
+	private void confirmAction() {
+		close();
+		selectionListeners.forEach(l -> l.selection(expert.get()));
+	}
+	
+	public void addSelectionListener(SelectionListener<Expert> listener) {
+		selectionListeners.add(listener);
+	}
+	
+	public static Promise<Expert> selectExpert(Shell parentShell, String tenderId, EvaluationFactorTypeEnum evaluationFactorTypeEnum) {
+		SelectStepExpertDialog dialog = new SelectStepExpertDialog(parentShell, tenderId, evaluationFactorTypeEnum);
+		return new Promise<>((s, f) -> {
+			dialog.addSelectionListener(s::accept);
+			dialog.open();
+		});
+	}
+	
+	/**
+	 * Return the initial size of the dialog.
+	 */
+	@Override
+	protected Point getInitialSize() {
+		return new Point(600, 400);
+	}
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/enums/DataCategoryEnum.java b/com.gx.obe.struct/src/com/gx/obe/struct/enums/DataCategoryEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a72531492bcbe254ba33870af1d8603e8c9a330
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/enums/DataCategoryEnum.java
@@ -0,0 +1,35 @@
+package com.gx.obe.struct.enums;
+
+import java.util.Map;
+
+import com.gx.obe.util.utils.EnumUtils;
+
+public enum DataCategoryEnum {
+	
+	NULL(""),
+	/**
+	 * 小范本数据表单
+	 */
+	TDI("TDI"),
+	/**
+	 * 小范本表格
+	 */
+	TT("TT"),
+	/**
+	 * 对象结构化数据
+	 */
+	MD("MD");
+	
+	public static Map<String, DataCategoryEnum> MAP = EnumUtils.toMap(values(), DataCategoryEnum::getKey);
+	
+	private String key;
+	
+	private DataCategoryEnum(String key) {
+		this.key = key;
+	}
+	
+	public String getKey() {
+		return key;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/enums/EvaluationFactorTypeEnum.java b/com.gx.obe.struct/src/com/gx/obe/struct/enums/EvaluationFactorTypeEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..83a9f80619f0be74a1dd1b300c39bbe55066f6af
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/enums/EvaluationFactorTypeEnum.java
@@ -0,0 +1,23 @@
+package com.gx.obe.struct.enums;
+
+import java.util.Map;
+
+import com.gx.obe.util.utils.EnumUtils;
+
+public enum EvaluationFactorTypeEnum {
+	
+	COMPLIANCE("compliance"), BUSINESS("business"), TECHNOLOGY("technology");
+	
+	public static Map<String, EvaluationFactorTypeEnum> MAP = EnumUtils.toMap(values(), EvaluationFactorTypeEnum::getKey);
+	
+	private String key;
+	
+	private EvaluationFactorTypeEnum(String key) {
+		this.key = key;
+	}
+	
+	public String getKey() {
+		return key;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/enums/ModelDataClassEnum.java b/com.gx.obe.struct/src/com/gx/obe/struct/enums/ModelDataClassEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..00227a17a2f014c75b9efebe1164675502c391ad
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/enums/ModelDataClassEnum.java
@@ -0,0 +1,30 @@
+package com.gx.obe.struct.enums;
+
+public enum ModelDataClassEnum {
+	
+	/**
+	 * 投标人基本情况
+	 */
+	BidderInfo,
+	/**
+	 * 营业执照
+	 */
+	BusinessLicense,
+	/**
+	 * 财务报告
+	 */
+	Finance,
+	/**
+	 * 业绩
+	 */
+	Performance,
+	/**
+	 * 项目负责人
+	 */
+	ProjectLeader,
+	/**
+	 * 企业体系认证证书
+	 */
+	Qualification;
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/enums/ModelDataTypeEnum.java b/com.gx.obe.struct/src/com/gx/obe/struct/enums/ModelDataTypeEnum.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5bfe2d7e967237074ed3bd0e90fb7aa4671ab2f
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/enums/ModelDataTypeEnum.java
@@ -0,0 +1,126 @@
+package com.gx.obe.struct.enums;
+
+import java.util.Map;
+
+import com.gx.obe.util.utils.EnumUtils;
+
+public enum ModelDataTypeEnum {
+	
+	/**
+	 * 投标人基本情况
+	 */
+	EQ_BidderBasicInfo("EQ_BidderBasicInfo", ModelDataClassEnum.BidderInfo),
+	/**
+	 * 营业执照
+	 */
+	EQ_BusinessLicense("EQ_BusinessLicense", ModelDataClassEnum.BusinessLicense),
+	/**
+	 * 财务报告
+	 */
+	EQ_FinancialReport("EQ_FinancialReport", ModelDataClassEnum.Finance),
+	/**
+	 * 项目负责人
+	 */
+	EQ_ProjectLeader("EQ_ProjectLeader", ModelDataClassEnum.ProjectLeader),
+	/**
+	 * 施工业绩
+	 */
+	EQ_Construction("EQ_Construction", ModelDataClassEnum.Performance),
+	/**
+	 * 勘察设计
+	 */
+	EQ_SurveyDesign("EQ_SurveyDesign", ModelDataClassEnum.Performance),
+	/**
+	 * 监理业绩
+	 */
+	EQ_Supervision("EQ_Supervision", ModelDataClassEnum.Performance),
+	/**
+	 * 采购业绩
+	 */
+	EQ_Procurement("EQ_Procurement", ModelDataClassEnum.Performance),
+	/**
+	 * 生产业绩
+	 */
+	EQ_Production("EQ_Production", ModelDataClassEnum.Performance),
+	/**
+	 * 安全生产许可证
+	 */
+	EQ_Qualification_SCXK("EQ_Qualification_SCXK", ModelDataClassEnum.Qualification),
+	/**
+	 * 质量体系认证证书
+	 */
+	EQ_Qualification_ZLTX("EQ_Qualification_ZLTX", ModelDataClassEnum.Qualification),
+	/**
+	 * 职业健康安全管理体系
+	 */
+	EQ_Qualification_ZYJK("EQ_Qualification_ZYJK", ModelDataClassEnum.Qualification),
+	/**
+	 * 环境管理体系认证证书
+	 */
+	EQ_Qualification_HBTX("EQ_Qualification_HBTX", ModelDataClassEnum.Qualification),
+	/**
+	 * 全国工业生产许可证
+	 */
+	EQ_Qualification_QGGYSCXK("EQ_Qualification_QGGYSCXK", ModelDataClassEnum.Qualification),
+	/**
+	 * 其他资质证书(华能企业资质证书)
+	 */
+	EQ_Qualification("EQ_Qualification", ModelDataClassEnum.Qualification),
+	/**
+	 * 国家级奖项(华能新增)
+	 */
+	EQ_Qualification_GJ_JX("EQ_Qualification_GJ_JX", ModelDataClassEnum.Qualification),
+	/**
+	 * 省部级奖励(华能新增)
+	 */
+	EQ_Qualification_SJ_JX("EQ_Qualification_SJ_JX", ModelDataClassEnum.Qualification),
+	/**
+	 * 所建工程国家级奖励
+	 */
+	EQ_Qualification_GJ_GCJX("EQ_Qualification_GJ_GCJX", ModelDataClassEnum.Qualification),
+	/**
+	 * 所建工程省部级奖励
+	 */
+	EQ_Qualification_SJ_GCJX("EQ_Qualification_SJ_GCJX", ModelDataClassEnum.Qualification),
+	/**
+	 * 资信等级(需要统一等级)
+	 */
+	EQ_Qualification_ZXDJ("EQ_Qualification_ZXDJ", ModelDataClassEnum.Qualification),
+	/**
+	 * 设计资质
+	 */
+	EQ_Qualification_SJZZ("EQ_Qualification_SJZZ", ModelDataClassEnum.Qualification),
+	/**
+	 * 施工资质
+	 */
+	EQ_Qualification_SGZZ("EQ_Qualification_SGZZ", ModelDataClassEnum.Qualification),
+	/**
+	 * 监理资质
+	 */
+	EQ_Qualification_JLZZ("EQ_Qualification_JLZZ", ModelDataClassEnum.Qualification),
+	/**
+	 * 检验报告
+	 */
+	EQ_Qualification_SurveyReport("EQ_Qualification_SurveyReport", ModelDataClassEnum.Qualification);
+	
+	
+	public static Map<String, ModelDataTypeEnum> MAP = EnumUtils.toMap(values(), ModelDataTypeEnum::getKey);
+	
+	private String key;
+	
+	private ModelDataClassEnum classEnum;
+	
+	private ModelDataTypeEnum(String key, ModelDataClassEnum classEnum) {
+		this.key = key;
+		this.classEnum = classEnum;
+	}
+	
+	public String getKey() {
+		return key;
+	}
+	
+	public ModelDataClassEnum getClassEnum() {
+		return classEnum;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/enums/PerformanceStatus.java b/com.gx.obe.struct/src/com/gx/obe/struct/enums/PerformanceStatus.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc4f9574b35fc94e7cacd4e8e3e7dad794a497f8
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/enums/PerformanceStatus.java
@@ -0,0 +1,39 @@
+package com.gx.obe.struct.enums;
+
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+
+import com.gx.obe.util.utils.EnumUtils;
+
+public enum PerformanceStatus {
+	/**
+	 * 进行中
+	 */
+	PROGRESS("00", "进行中"),
+	/**
+	 * 已完成
+	 */
+	COMPLETED("01", "已投产");
+	
+	public static Map<String, PerformanceStatus> MAP = EnumUtils.toMap(values(), PerformanceStatus::getKey);
+	
+	public static Function<String, String> keyToValueFun = t -> Optional.ofNullable(t).map(MAP::get).map(PerformanceStatus::getName).orElse("未知状态");
+	
+	private String key;
+	private String name;
+	
+	private PerformanceStatus(String key, String name) {
+		this.key = key;
+		this.name = name;
+	}
+	
+	public String getKey() {
+		return key;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/factory/ModelDataFactory.java b/com.gx.obe.struct/src/com/gx/obe/struct/factory/ModelDataFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ac967946e0142f43e614deb0e71bdb6cdad21eb
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/factory/ModelDataFactory.java
@@ -0,0 +1,1476 @@
+package com.gx.obe.struct.factory;
+
+import java.io.File;
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.widgets.Composite;
+
+import com.gx.obe.common.icons.IconsActivator;
+import com.gx.obe.component.form.FForm;
+import com.gx.obe.component.rx.RxSwt;
+import com.gx.obe.component.table.FTable;
+import com.gx.obe.component.utils.CompositeUtils;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.struct.beans.AttachmentFile;
+import com.gx.obe.struct.beans.BidderBasicInfo;
+import com.gx.obe.struct.beans.BusinessLicense;
+import com.gx.obe.struct.beans.Certificate;
+import com.gx.obe.struct.beans.Finance;
+import com.gx.obe.struct.beans.ModelData;
+import com.gx.obe.struct.beans.Performance;
+import com.gx.obe.struct.beans.ProjectLeader;
+import com.gx.obe.struct.beans.Qualification;
+import com.gx.obe.struct.beans.WorkExperience;
+import com.gx.obe.struct.enums.ModelDataTypeEnum;
+import com.gx.obe.struct.enums.PerformanceStatus;
+import com.gx.obe.struct.inters.IModelData;
+import com.gx.obe.struct.inters.IModelDataDetail;
+import com.gx.obe.struct.service.AttachmentFileService;
+import com.gx.obe.struct.service.BidderInfoService;
+import com.gx.obe.struct.service.BusinessLicenseService;
+import com.gx.obe.struct.service.CertificateService;
+import com.gx.obe.struct.service.FinanceService;
+import com.gx.obe.struct.service.PerformanceService;
+import com.gx.obe.struct.service.ProjectLeaderService;
+import com.gx.obe.struct.service.QualificationService;
+import com.gx.obe.struct.service.WorkExperienceService;
+import com.gx.obe.util.utils.NumberFormatUtils;
+import com.gx.obe.util.utils.RuntimeUtils;
+import com.swtdesigner.ResourceManager;
+
+public class ModelDataFactory {
+	
+	public static IModelData create(Composite tableParent, IModelDataDetail modelDataDetail, ModelDataTypeEnum modelDataTypeEnum) {
+		CompositeUtils.disposeChildren(tableParent);
+		switch (modelDataTypeEnum) {
+			case EQ_BidderBasicInfo:
+				return initBidderBasicInfo(tableParent, modelDataDetail);
+			case EQ_BusinessLicense:
+				return initBusinessLicense(tableParent, modelDataDetail);
+			case EQ_Construction:
+				return initConstruction(tableParent, modelDataDetail);
+			case EQ_FinancialReport:
+				return initFinancialReport(tableParent, modelDataDetail);
+			case EQ_Procurement:
+				return initProcurement(tableParent, modelDataDetail);
+			case EQ_Production:
+				return initProduction(tableParent, modelDataDetail);
+			case EQ_ProjectLeader:
+				return initProjectLeader(tableParent, modelDataDetail);
+			case EQ_Qualification:
+				return initQualification(tableParent, modelDataDetail);
+			case EQ_Qualification_GJ_GCJX:
+				return initQualification_GJ_GCJX(tableParent, modelDataDetail);
+			case EQ_Qualification_GJ_JX:
+				return initQualification_GJ_JX(tableParent, modelDataDetail);
+			case EQ_Qualification_HBTX:
+				return initQualification_HBTX(tableParent, modelDataDetail);
+			case EQ_Qualification_JLZZ:
+				return initQualification_JLZZ(tableParent, modelDataDetail);
+			case EQ_Qualification_QGGYSCXK:
+				return initQualification_QGGYSCXK(tableParent, modelDataDetail);
+			case EQ_Qualification_SCXK:
+				return initQualification_SCXK(tableParent, modelDataDetail);
+			case EQ_Qualification_SGZZ:
+				return initQualification_SGZZ(tableParent, modelDataDetail);
+			case EQ_Qualification_SJZZ:
+				return initQualification_SJZZ(tableParent, modelDataDetail);
+			case EQ_Qualification_SJ_GCJX:
+				return initQualification_SJ_GCJX(tableParent, modelDataDetail);
+			case EQ_Qualification_SJ_JX:
+				return initQualification_SJ_JX(tableParent, modelDataDetail);
+			case EQ_Qualification_SurveyReport:
+				return initQualification_SurveyReport(tableParent, modelDataDetail);
+			case EQ_Qualification_ZLTX:
+				return initQualification_ZLTX(tableParent, modelDataDetail);
+			case EQ_Qualification_ZXDJ:
+				return initQualification_ZXDJ(tableParent, modelDataDetail);
+			case EQ_Qualification_ZYJK:
+				return initQualification_ZYJK(tableParent, modelDataDetail);
+			case EQ_Supervision:
+				return initSupervision(tableParent, modelDataDetail);
+			case EQ_SurveyDesign:
+				return initSurveyDesign(tableParent, modelDataDetail);
+		}
+		
+		return null;
+	}
+	
+	/**
+	 * @Description: 投标人基本情况
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initBidderBasicInfo(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final BidderInfoService bidderInfoService = new BidderInfoService();
+			
+			private FTable<BidderBasicInfo> fTable;
+			
+			protected void init() {
+				fTable = new FTable<BidderBasicInfo>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("投标人名称", BidderBasicInfo::getCompanyName);
+						new ContentColumn("注册地址", BidderBasicInfo::getRegisterLocation);
+						new ContentColumn("联系人", BidderBasicInfo::getLinkMan);
+						new ContentColumn("组织结构", BidderBasicInfo::getOrgStructure);
+						new ContentColumn("法人姓名", BidderBasicInfo::getLegalRepresentativeName);
+						new ContentColumn("技术负责人姓名", BidderBasicInfo::getTechnicalDirectorName);
+						new ContentColumn("成立时间", BidderBasicInfo::getSetupTime);
+						new ContentColumn("企业资质等级", BidderBasicInfo::getCompanyQualificationLevel);
+						new ContentColumn("注册资金(万元)", BidderBasicInfo::getRegisteredCapital);
+						new ContentColumn("营业执照号", BidderBasicInfo::getBussinessLicense);
+						new ContentColumn("开户银行", BidderBasicInfo::getDepositBank);
+						new ContentColumn("银行账号", BidderBasicInfo::getBankAccount);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCompanyName() + "基本情况表"));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<BidderBasicInfo> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("投标人名称", BidderBasicInfo::getCompanyName); t.add("注册地址", BidderBasicInfo::getRegisterLocation);
+						t.add("联系人", BidderBasicInfo::getLinkMan); t.add("电话", BidderBasicInfo::getLinkManPhone);
+						t.add("邮政编码", BidderBasicInfo::getPostalCode); t.add("传真", BidderBasicInfo::getLinkManFax);
+						t.add("网址", BidderBasicInfo::getLinkManWebsite); t.add("组织结构", BidderBasicInfo::getOrgStructure);
+						t.add("法人姓名", BidderBasicInfo::getLegalRepresentativeName); t.add("技术负责人姓名", BidderBasicInfo::getTechnicalDirectorName);
+						t.add("法人技术职称", BidderBasicInfo::getLegalRepresentativeTitle); t.add("技术负责人职称", BidderBasicInfo::getTechnicalDirectorTitle);
+						t.add("法人电话", BidderBasicInfo::getLegalRepresentativePhone); t.add("技术负责人电话", BidderBasicInfo::getTechnicalDirectorPhone);
+						t.add("成立时间", BidderBasicInfo::getSetupTime); t.add("企业资质等级", BidderBasicInfo::getCompanyQualificationLevel);
+						t.add("注册资金(万元)", BidderBasicInfo::getRegisteredCapital); t.add("营业执照号", BidderBasicInfo::getBussinessLicense);
+						t.add("开户银行", BidderBasicInfo::getDepositBank); t.add("银行账号", BidderBasicInfo::getBankAccount);
+						t.add("高级职称人数", BidderBasicInfo::getSeniorProfessionalPostNumber); t.add("项目经理人数", BidderBasicInfo::getPurchaserNumber);
+						t.add("中级职称人数", BidderBasicInfo::getMediumProfessionalPostNumber); t.add("技工人数", BidderBasicInfo::getArtisanNumber);
+						t.add("初级职称人数", BidderBasicInfo::getPrimaryProfessionalPostNumber); t.add("员工总人数", BidderBasicInfo::getEmployeeNumber);
+						t.addLong("企业性质", BidderBasicInfo::getEnterpriseNature);
+						t.addLong("经营范围", BidderBasicInfo::getBusinessScope);
+						t.addLong("股权结构", BidderBasicInfo::getEquityStructure);
+						t.addBig("拟投入项目设备", BidderBasicInfo::getPreInputDevice);
+						t.addBig("关联企业情况", BidderBasicInfo::getRelatedCompanyInfo);
+						t.addBig("服务能力", BidderBasicInfo::getServiceAbility);
+						t.addBig("备注", BidderBasicInfo::getMemo);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> bidderInfoService.getBidderBasicInfoList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 营业执照
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initBusinessLicense(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final BusinessLicenseService businessLicenseService = new BusinessLicenseService();
+			
+			private FTable<BusinessLicense> fTable;
+			
+			protected void init() {
+				fTable = new FTable<BusinessLicense>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("统一社会信用代码", BusinessLicense::getRegisterNumber);
+						new ContentColumn("公司名称", BusinessLicense::getCompanyName);
+						new ContentColumn("住所", BusinessLicense::getCompanyAddress);
+						new ContentColumn("法定代表人", BusinessLicense::getLegalRepresentative);
+						new ContentColumn("注册资本(万元)", BusinessLicense::getRegisterCapital);
+						new ContentColumn("成立日期", BusinessLicense::getEstablishDate);
+						new ContentColumn("营业期限", d -> d.getBusnissTermStartDate() + "至" + d.getBusnissTermEndtDate());
+						new ContentColumn("登记机关", BusinessLicense::getRegisterInstitution);
+						new ContentColumn("企业类型", BusinessLicense::getCompanyType);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCompanyName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<BusinessLicense> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("统一社会信用代码", BusinessLicense::getRegisterNumber);
+						t.add("公司名称", BusinessLicense::getCompanyName);
+						t.add("住所", BusinessLicense::getCompanyAddress);
+						t.add("法定代表人", BusinessLicense::getLegalRepresentative);
+						t.add("注册资本(万元)", BusinessLicense::getRegisterCapital);
+						t.add("成立日期", BusinessLicense::getEstablishDate);
+						t.add("营业期限", d -> d.getBusnissTermStartDate() + "至" + d.getBusnissTermEndtDate());
+						t.add("登记机关", BusinessLicense::getRegisterInstitution);
+						t.add("企业类型", BusinessLicense::getCompanyType);
+						t.addBig("经营范围", BusinessLicense::getBusinessScope);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> businessLicenseService.getBusinessLicenseList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 施工业绩
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initConstruction(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final PerformanceService performanceService = new PerformanceService();
+			
+			private FTable<Performance> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Performance>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("企业名称", Performance::getSupplierName);
+						new ContentColumn("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						new ContentColumn("项目名称", Performance::getProjectName);
+						new ContentColumn("项目所在地", Performance::getProjectAddress);
+						new ContentColumn("发包人名称", Performance::getBuyerName);
+						new ContentColumn("合同金额(万元)", Performance::getSingningTotal);
+						new ContentColumn("开工日期", Performance::getStartTime);
+						new ContentColumn("竣工/计划竣工日期", Performance::getEndTime);
+						new ContentColumn("项目经理", Performance::getProjectManager);
+						new ContentColumn("技术负责人", Performance::getTechnicalDirector);
+						new ContentColumn("总监理工程师", Performance::getChiefSupervisionEngineer);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getProjectName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Performance> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("企业名称", Performance::getSupplierName); t.add("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						t.add("项目名称", Performance::getProjectName); t.add("项目所在地", Performance::getProjectAddress);
+						t.add("发包人名称", Performance::getBuyerName); t.add("发包人地址", Performance::getBuyerAddress);
+						t.add("发包人电话", Performance::getBuyerPhoneNumber); t.add("合同金额(万元)", Performance::getSingningTotal);
+						t.add("开工日期", Performance::getStartTime); t.add("竣工/计划竣工日期", Performance::getEndTime);
+						t.addLong("承担的工作", Performance::getWorkUndertaken);
+						t.addLong("项目质量", Performance::getProjectQuantity);
+						t.add("项目经理", Performance::getProjectManager); t.add("技术负责人", Performance::getTechnicalDirector);
+						t.add("总监理工程师", Performance::getChiefSupervisionEngineer); t.add("总监理工程师电话", Performance::getCsePhoneNumber);
+						t.addBig("项目描述", Performance::getProjectDesc);
+						t.addLong("备注", Performance::getMemo);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> performanceService.getPerformanceList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 财务报告
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initFinancialReport(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final FinanceService financeService = new FinanceService();
+			
+			private FTable<Finance> fTable;
+			
+			protected void init() {
+				
+				final Function<BigDecimal, String> toString = t -> Optional.ofNullable(t).map(NumberFormatUtils::format).orElse(null);
+				
+				fTable = new FTable<Finance>(tableParent, SWT.NONE) {
+					
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("企业名称", Finance::getCompanyName);
+						new ContentColumn("财务报告年度", Finance::getAnnual);
+						new ContentColumn("资产总额(万元)", toString.compose(Finance::getTotal));
+						new ContentColumn("负债总额(万元)", toString.compose(Finance::getTotalliabilities));
+						new ContentColumn("资产负债率(%)", toString.compose(Finance::getLiabilitiesRate));
+						new ContentColumn("主营业务收入(万元)", toString.compose(Finance::getPrimeOperatingRevenue));
+						new ContentColumn("净利润(万元)", toString.compose(Finance::getRetainedProfits));
+						new ContentColumn("净利率(%)", toString.compose(Finance::getProfitRatio));
+					}
+				};
+				
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getAnnual() + "年度财务报告"));
+				
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Finance> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("企业名称", Finance::getCompanyName);
+						t.add("财务报告年度", Finance::getAnnual);
+						t.add("资产总额(万元)", toString.compose(Finance::getTotal));
+						t.add("主营业务收入(万元)", toString.compose(Finance::getPrimeOperatingRevenue));
+						t.add("负债总额(万元)", toString.compose(Finance::getTotalliabilities));
+						t.add("净利润(万元)", toString.compose(Finance::getRetainedProfits));
+						t.add("资产负债率(%)", toString.compose(Finance::getLiabilitiesRate));
+						t.add("净利率(%)", toString.compose(Finance::getProfitRatio));
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> financeService.getFinanceList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 采购业绩
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initProcurement(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final PerformanceService performanceService = new PerformanceService();
+			
+			private FTable<Performance> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Performance>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("企业名称", Performance::getSupplierName);
+						new ContentColumn("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						new ContentColumn("设备名称", Performance::getDeviceName);
+						new ContentColumn("规格和型号", Performance::getDevicetypeSpecification);
+						new ContentColumn("项目名称", Performance::getProjectName);
+						new ContentColumn("总容量", Performance::getTotalCapacity);
+						new ContentColumn("台数", Performance::getNumber);
+						new ContentColumn("买方名称", Performance::getBuyerName);
+						new ContentColumn("联系人", Performance::getBuyerLinkman);
+						new ContentColumn("联系方式", Performance::getBuyerPhoneNumber);
+						new ContentColumn("合同时间", Performance::getContractTime);
+						new ContentColumn("签约合同价(万元)", Performance::getSingningTotal);
+						new ContentColumn("投运/计划投运日期", Performance::getCommissioningTime);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getSupplierName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Performance> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("企业名称", Performance::getSupplierName); t.add("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						t.add("设备名称", Performance::getDeviceName); t.add("规格和型号", Performance::getDevicetypeSpecification);
+						t.add("项目名称", Performance::getProjectName); t.add("总容量", Performance::getTotalCapacity);
+						t.add("台数", Performance::getNumber); t.add("买方名称", Performance::getBuyerName);
+						t.add("联系人", Performance::getBuyerLinkman); t.add("联系方式", Performance::getBuyerPhoneNumber);
+						t.add("合同时间", Performance::getContractTime); t.add("签约合同价(万元)", Performance::getSingningTotal);
+						t.add("投运/计划投运日期", Performance::getCommissioningTime); t.addNull();
+						t.addBig("备注", Performance::getMemo);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> performanceService.getPerformanceList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 生产业绩
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initProduction(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final PerformanceService performanceService = new PerformanceService();
+			
+			private FTable<Performance> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Performance>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("企业名称", Performance::getSupplierName);
+						new ContentColumn("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						new ContentColumn("项目名称", Performance::getProjectName);
+						new ContentColumn("项目所在地", Performance::getProjectAddress);
+						new ContentColumn("发包人名称", Performance::getBuyerName);
+						new ContentColumn("签约价格(万元)", Performance::getSingningTotal);
+						new ContentColumn("开工日期", Performance::getStartTime);
+						new ContentColumn("竣工/计划竣工日期", Performance::getEndTime);
+						new ContentColumn("项目经理", Performance::getProjectManager);
+						new ContentColumn("技术负责人", Performance::getTechnicalDirector);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getProjectName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Performance> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("企业名称", Performance::getSupplierName); t.add("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						t.add("项目名称", Performance::getProjectName); t.add("项目所在地", Performance::getProjectAddress);
+						t.add("发包人名称", Performance::getBuyerName); t.add("发包人地址", Performance::getBuyerAddress);
+						t.add("发包人电话", Performance::getBuyerPhoneNumber); t.add("签约价格(万元)", Performance::getSingningTotal);
+						t.add("开工日期", Performance::getStartTime); t.add("竣工/计划竣工日期", Performance::getEndTime);
+						t.addLong("承担的工作", Performance::getWorkUndertaken);
+						t.addLong("项目质量", Performance::getProjectQuantity);
+						t.add("项目经理", Performance::getProjectManager); t.add("技术负责人", Performance::getTechnicalDirector);
+						t.addBig("项目描述", Performance::getProjectDesc);
+						t.addLong("备注", Performance::getMemo);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> performanceService.getPerformanceList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 项目负责人
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initProjectLeader(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final ProjectLeaderService projectLeaderService = new ProjectLeaderService();
+			private final CertificateService certificateService = new CertificateService();
+			private final WorkExperienceService workExperienceService = new WorkExperienceService();
+			
+			private FTable<ProjectLeader> fTable;
+			
+			protected void init() {
+				fTable = new FTable<ProjectLeader>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("姓名", ProjectLeader::getLeaderName);
+						new ContentColumn("身份证号", ProjectLeader::getIdnumber);
+						new ContentColumn("年龄", ProjectLeader::getAge);
+						new ContentColumn("职务", ProjectLeader::getJobTitle);
+						new ContentColumn("职称", ProjectLeader::getProfessionalTitle);
+						new ContentColumn("学历", ProjectLeader::getEducation);
+						new ContentColumn("毕业学校", ProjectLeader::getGraduateSchool);
+						new ContentColumn("专业", ProjectLeader::getGraduateMajor);
+						new ContentColumn("工作经验(年)", ProjectLeader::getWorkExperience);
+						new ContentColumn("公司名称", ProjectLeader::getCompanyName);
+						new ContentColumn("本专业工作经验(年)", ProjectLeader::getCurrentMajorExperience);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCompanyName() + "基本情况表"));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<ProjectLeader> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("姓名", ProjectLeader::getLeaderName); t.add("身份证号", ProjectLeader::getIdnumber);
+						t.add("年龄", ProjectLeader::getAge); t.add("职务", ProjectLeader::getJobTitle);
+						t.add("职称", ProjectLeader::getProfessionalTitle); t.add("学历", ProjectLeader::getEducation);
+						t.add("毕业学校", ProjectLeader::getGraduateSchool); t.add("专业", ProjectLeader::getGraduateMajor);
+						t.add("工作经验(年)", ProjectLeader::getWorkExperience); t.add("公司名称", ProjectLeader::getCompanyName);
+						t.add("本专业工作经验(年)", ProjectLeader::getCurrentMajorExperience); t.addNull();
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addSubpage("证书列表", p -> {
+					FTable<Certificate> table = new FTable<Certificate>(p, SWT.NONE) {
+
+						private final AttachmentFileService attachmentFileService = new AttachmentFileService();
+						
+						protected void init() {
+							new IndexColumn("序号");
+							new ContentColumn("证书编号", Certificate::getCertificateNo);
+							new ContentColumn("证书名称", Certificate::getCertificateName);
+							new ContentColumn("证书等级", Certificate::getCertificateLevel);
+							new LinkContentColumn("查看", "查看", ResourceManager.getPluginImage(IconsActivator.PLUGIN_ID, "icons/btn/blue/view.png"), t -> {
+								String bidFilePath = Constants.getBidFilePath(t.getTenderId(), supplierId.get());
+								RxSwt.run(() -> attachmentFileService.getAttachmentFileList(t.getId())).checkWidget(this).exe(attachmentFileList -> {
+									Optional<File> fileOptional = Optional.ofNullable(attachmentFileList).map(List::stream).flatMap(Stream::findFirst).map(AttachmentFile::getFileUrl).map(bidFilePath::concat).map(File::new).filter(File::exists);
+									if (fileOptional.isPresent()) {
+										RuntimeUtils.openFIle(fileOptional.get());
+									} else {
+										MessageDialog.openShortMessage("文件不存在!");
+									}
+								});
+							});
+						}
+					};
+					fTable.addSelectionListener(t -> RxSwt.run(() -> certificateService.getCertificateList(t.getId())).checkWidget(table).exe(table::refresh));
+					return table;
+				});
+				modelDataDetail.addSubpage("个人经历", p -> {
+					FTable<WorkExperience> table = new FTable<WorkExperience>(p, SWT.NONE) {
+						protected void init() {
+							new IndexColumn("序号");
+							new ContentColumn("投运时间/竣工时间", WorkExperience::getTime);
+							new ContentColumn("项目名称", WorkExperience::getProjectName);
+							new ContentColumn("容量(MW)", WorkExperience::getCapacity);
+							new ContentColumn("担任职务", WorkExperience::getJobTitle);
+							new ContentColumn("承担的工作(简述)", WorkExperience::getBearWork);
+							new ContentColumn("发包人及联系电话", WorkExperience::getContractInfo);
+						}
+					};
+					fTable.addSelectionListener(t -> RxSwt.run(() -> workExperienceService.getWorkExperienceList(t.getId())).checkWidget(table).exe(table::refresh));
+					return table;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> projectLeaderService.getProjectLeaderList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 企业资质
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("证书等级", Qualification::getAwardLevel);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("证书等级", Qualification::getAwardLevel);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 所建工程国家级奖励
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_GJ_GCJX(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发奖单位", Qualification::getIssueAuthority);
+						new ContentColumn("获奖工程名称", Qualification::getAwardProjectName);
+						new ContentColumn("获奖年份", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发奖单位", Qualification::getIssueAuthority);
+						t.add("获奖工程名称", Qualification::getAwardProjectName);
+						t.add("获奖年份", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 国家级奖项
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_GJ_JX(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发奖单位", Qualification::getIssueAuthority);
+						new ContentColumn("获奖年份", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发奖单位", Qualification::getIssueAuthority);
+						t.add("获奖年份", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 环境管理体系认证证书
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_HBTX(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("认证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+						new ContentColumn("有效期至", Qualification::getPeriodValidity);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+						t.add("有效期至", Qualification::getPeriodValidity);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 监理资质
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_JLZZ(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("证书等级", Qualification::getAwardLevel);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("证书等级", Qualification::getAwardLevel);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 全国工业生产许可证
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_QGGYSCXK(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("认证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+						new ContentColumn("有效期至", Qualification::getPeriodValidity);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("认证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+						t.add("有效期至", Qualification::getPeriodValidity);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 施工资质
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_SGZZ(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("证书等级", Qualification::getAwardLevel);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("证书等级", Qualification::getAwardLevel);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 设计资质
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_SJZZ(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("证书等级", Qualification::getAwardLevel);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("证书等级", Qualification::getAwardLevel);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 安全生产许可证
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_SCXK(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("认证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+						new ContentColumn("有效期至", Qualification::getPeriodValidity);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("认证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+						t.add("有效期至", Qualification::getPeriodValidity);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 所建工程省部级级奖励
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_SJ_GCJX(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发奖单位", Qualification::getIssueAuthority);
+						new ContentColumn("获奖工程名称", Qualification::getAwardProjectName);
+						new ContentColumn("获奖年份", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发奖单位", Qualification::getIssueAuthority);
+						t.add("获奖工程名称", Qualification::getAwardProjectName);
+						t.add("获奖年份", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 省部级奖励
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_SJ_JX(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发奖单位", Qualification::getIssueAuthority);
+						new ContentColumn("获奖年份", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发奖单位", Qualification::getIssueAuthority);
+						t.add("获奖年份", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 检验报告
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_SurveyReport(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("证书等级", Qualification::getAwardLevel);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("证书等级", Qualification::getAwardLevel);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 质量体系认证证书
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_ZLTX(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("认证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+						new ContentColumn("有效期至", Qualification::getPeriodValidity);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+						t.add("有效期至", Qualification::getPeriodValidity);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 资信等级
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_ZXDJ(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("证书等级", Qualification::getAwardLevel);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+						new ContentColumn("有效期至", Qualification::getPeriodValidity);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("证书等级", Qualification::getAwardLevel);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+						t.add("有效期至", Qualification::getPeriodValidity);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 职业健康安全管理体系
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initQualification_ZYJK(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final QualificationService qualificationService = new QualificationService();
+			
+			private FTable<Qualification> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Qualification>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("证书名称", Qualification::getCertificateName);
+						new ContentColumn("证书编号", Qualification::getCertificateNumber);
+						new ContentColumn("企业名称", Qualification::getCompanyName);
+						new ContentColumn("发证单位", Qualification::getIssueAuthority);
+						new ContentColumn("发证日期", Qualification::getIssueDate);
+						new ContentColumn("有效期至", Qualification::getPeriodValidity);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getCertificateName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Qualification> fform = new FForm<>(p, 1);
+					fform.init(t -> {
+						t.add("证书编号", Qualification::getCertificateNumber);
+						t.add("企业名称", Qualification::getCompanyName);
+						t.add("发证单位", Qualification::getIssueAuthority);
+						t.add("发证日期", Qualification::getIssueDate);
+						t.add("有效期至", Qualification::getPeriodValidity);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> qualificationService.getQualificationList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 监理业绩
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initSupervision(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final PerformanceService performanceService = new PerformanceService();
+			
+			private FTable<Performance> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Performance>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("企业名称", Performance::getSupplierName);
+						new ContentColumn("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						new ContentColumn("项目名称", Performance::getProjectName);
+						new ContentColumn("项目所在地", Performance::getProjectAddress);
+						new ContentColumn("签约合同价(万元)", Performance::getSingningTotal);
+						new ContentColumn("委托人名称", Performance::getBuyerName);
+						new ContentColumn("委托人地址", Performance::getBuyerAddress);
+						new ContentColumn("委托人电话", Performance::getBuyerPhoneNumber);
+						new ContentColumn("总监理工程师", Performance::getChiefSupervisionEngineer);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getProjectName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Performance> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("企业名称", Performance::getSupplierName); t.add("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						t.add("项目名称", Performance::getProjectName); t.add("项目所在地", Performance::getProjectAddress);
+						t.add("委托人名称", Performance::getBuyerName); t.add("委托人地址", Performance::getBuyerAddress);
+						t.add("签约合同价(万元)", Performance::getSingningTotal); t.add("委托人电话", Performance::getBuyerPhoneNumber);
+						t.add("总监理工程师", Performance::getChiefSupervisionEngineer); t.addNull();
+						t.addLong("监理服务期限", Performance::getServiceDesc);
+						t.addLong("监理内容", Performance::getSupervisionCcontent);
+						t.addBig("项目描述", Performance::getProjectDesc);
+						t.addBig("备注", Performance::getMemo);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> performanceService.getPerformanceList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+	/**
+	 * @Description: 勘察设计
+	 * @author chenxw
+	 * @param tableParent
+	 * @param modelDataDetail
+	 * @return 
+	 */
+	private static IModelData initSurveyDesign(Composite tableParent, IModelDataDetail modelDataDetail) {
+		return new IModelData() {
+			
+			private final PerformanceService performanceService = new PerformanceService();
+			
+			private FTable<Performance> fTable;
+			
+			protected void init() {
+				fTable = new FTable<Performance>(tableParent, SWT.NONE) {
+					protected void init() {
+						new IndexColumn("序号");
+						new ContentColumn("企业名称", Performance::getSupplierName);
+						new ContentColumn("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						new ContentColumn("项目名称", Performance::getProjectName);
+						new ContentColumn("项目所在地", Performance::getProjectAddress);
+						new ContentColumn("发包人名称", Performance::getBuyerName);
+						new ContentColumn("合同价格(万元)", Performance::getSingningTotal);
+						new ContentColumn("勘察设计服务期限", Performance::getServiceDesc);
+						new ContentColumn("勘察设计内容", Performance::getDesignRange);
+						new ContentColumn("负责人/总工程师", Performance::getChiefSupervisionEngineer);
+					}
+				};
+				fTable.addSelectionListener(t -> modelDataDetail.refreshTitle(t.getProjectName()));
+				modelDataDetail.addBasicSubpage(p -> {
+					FForm<Performance> fform = new FForm<>(p, 2);
+					fform.init(t -> {
+						t.add("企业名称", Performance::getSupplierName); t.add("业绩状态", PerformanceStatus.keyToValueFun.compose(Performance::getStatus));
+						t.add("项目名称", Performance::getProjectName); t.add("项目所在地", Performance::getProjectAddress);
+						t.add("发包人名称", Performance::getBuyerName); t.add("发包人地址", Performance::getBuyerAddress);
+						t.add("发包人电话", Performance::getBuyerPhoneNumber); t.add("合同价格(万元)", Performance::getSingningTotal);
+						t.add("勘察设计服务期限", Performance::getServiceDesc); t.add("勘察设计内容", Performance::getDesignRange);
+						t.add("负责人/总工程师", Performance::getChiefSupervisionEngineer); t.addNull();
+						t.addBig("项目描述", Performance::getProjectDesc);
+						t.addBig("备注", Performance::getMemo);
+					});
+					fTable.addSelectionListener(fform::refresh);
+					return fform;
+				});
+				modelDataDetail.addAttachmentSubpage(c -> fTable.addSelectionListener(t -> c.accept(supplierId.get(), t.getId())));
+			}
+			
+			public void refresh(ModelData modelData) {
+				supplierId.set(modelData.getSupplierId());
+				RxSwt.run(() -> performanceService.getPerformanceList(modelData.getTenderId(), modelData.getId())).checkWidget(fTable).exe(l -> {
+					count.set(l.size());
+					fTable.refresh(l);
+				});
+			}
+		};
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentFactory.java b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..68e92d02ad553b647833af3537c42a02eeba56dd
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentFactory.java
@@ -0,0 +1,73 @@
+package com.gx.obe.struct.handler;
+
+import java.util.List;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+import com.gx.obe.struct.inters.IFactorClearBidContent;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+import com.gx.obe.web.service.SupplierService;
+import com.gx.obe.web.service.evaluation.EvaluationFactorService;
+
+public class FactorClearBidContentFactory {
+	
+	private SupplierService supplierService = new SupplierService();
+	private EvaluationFactorService evaluationFactorService = new EvaluationFactorService();
+	private SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	
+	private String tenderId;
+	private List<Supplier> supplierList;
+	private List<SupplierEvaluationFactor> supplierEvaluationFactorList;
+	
+	public FactorClearBidContentFactory(String tenderId) {
+		this.tenderId = tenderId;
+		this.supplierList = supplierService.getOpenBidSuccessSupplier(tenderId);
+		this.supplierEvaluationFactorList = supplierEvaluationFactorService.getEntityListByTenderId(tenderId);
+	}
+	
+	public IFactorClearBidContent create(String audit) {
+		List<EvaluationFactor> factorList = evaluationFactorService.getAllEvaluationFactorList(tenderId, audit);
+		return new IFactorClearBidContent() {
+			
+			@Override
+			public String getTableName() {
+				if (EvaluationFactorEnum.AUDIT_COMPLIANCE.equals(audit)) {
+					return "符合性指标清标表";
+				}
+				if (EvaluationFactorEnum.AUDIT_SCORE.equals(audit)) {
+					return "打分指标清标表";
+				}
+				return null;
+			}
+			
+			public String getFileName() {
+				if (EvaluationFactorEnum.AUDIT_COMPLIANCE.equals(audit)) {
+					return "指标清标意见-符合性.xlsx";
+				}
+				if (EvaluationFactorEnum.AUDIT_SCORE.equals(audit)) {
+					return "指标清标意见-打分.xlsx";
+				}
+				return null;
+			}
+			
+			public List<Supplier> getSupplierList() {
+				return supplierList;
+			}
+			
+			public List<EvaluationFactor> getFactorList() {
+				return factorList;
+			}
+			
+			public List<SupplierEvaluationFactor> getSupplierEvaluationFactorList() {
+				return supplierEvaluationFactorList;
+			}
+
+			public String getContent(SupplierEvaluationFactor supplierEvaluationFactor) {
+				return supplierEvaluationFactor.getFactorResponse();
+			}
+		};
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentHandler.java b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..d52074f249c9bef29f4007df39cf810b3ba6fe23
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentHandler.java
@@ -0,0 +1,58 @@
+package com.gx.obe.struct.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.struct.inters.IFactorClearBidContent;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+import com.gx.obe.web.vo.FactorClearBidContent;
+
+public class FactorClearBidContentHandler implements IFactorClearBidContent {
+	
+	private final SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	
+	private final Optional<TenderProjectEntity> tenderProject;
+	
+	private final Optional<FactorClearBidContent> factorClearBidContent;
+	
+	public FactorClearBidContentHandler(TenderProjectEntity tenderProject) {
+		this.tenderProject = Optional.ofNullable(tenderProject);
+		this.factorClearBidContent = this.tenderProject.map(TenderProjectEntity::getId).map(supplierEvaluationFactorService::getScoreFactorClearBidContent);
+	}
+	
+	@Override
+	public String getTableName() {
+		return null;
+	}
+	
+	@Override
+	public String getFileName() {
+		return "商务技术评审因素汇总表.xlsx";
+	}
+	
+	@Override
+	public List<Supplier> getSupplierList() {
+		return factorClearBidContent.map(FactorClearBidContent::getSupplierList).orElseGet(ArrayList::new);
+	}
+	
+	@Override
+	public List<EvaluationFactor> getFactorList() {
+		return factorClearBidContent.map(FactorClearBidContent::getFactorList).orElseGet(ArrayList::new);
+	}
+	
+	@Override
+	public List<SupplierEvaluationFactor> getSupplierEvaluationFactorList() {
+		return factorClearBidContent.map(FactorClearBidContent::getSupplierEvaluationFactorList).orElseGet(ArrayList::new);
+	}
+
+	@Override
+	public String getContent(SupplierEvaluationFactor supplierEvaluationFactor) {
+		return supplierEvaluationFactor.getOpinion();
+	}
+	
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentStepHandler.java b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentStepHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..43af9a3edc0d431a6394ea8ef406d1b0578c1de8
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidContentStepHandler.java
@@ -0,0 +1,87 @@
+package com.gx.obe.struct.handler;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.components.core.enumeration.EvaluationStepEnum;
+import com.gx.obe.message.Messages;
+import com.gx.obe.struct.enums.EvaluationFactorTypeEnum;
+import com.gx.obe.struct.inters.IFactorClearBidContent;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+import com.gx.obe.web.entity.evaluation.EvaluationStep;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+import com.gx.obe.web.vo.FactorClearBidContent;
+
+public class FactorClearBidContentStepHandler implements IFactorClearBidContent {
+	
+	private final SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	
+	private final Optional<EvaluationStep> evaluationStep;
+	
+	private final Optional<FactorClearBidContent> factorClearBidContent;
+	
+	public FactorClearBidContentStepHandler(EvaluationStep evaluationStep) {
+		this.evaluationStep = Optional.ofNullable(evaluationStep);
+		this.factorClearBidContent = this.evaluationStep.map(EvaluationStep::getId).map(supplierEvaluationFactorService::getFactorClearBidContent);
+	}
+	
+	@Override
+	public String getTableName() {
+		Optional<EvaluationFactorTypeEnum> evaluationFactorTypeEnum = evaluationStep.map(t -> t.getEvaluationParamByKey(EvaluationStepEnum.EVALUATION_FACTOR_TYPE)).map(EvaluationFactorTypeEnum.MAP::get);
+		if (!evaluationFactorTypeEnum.isPresent()) {
+			return null;
+		}
+		switch (evaluationFactorTypeEnum.get()) {
+			case COMPLIANCE:
+				return "符合性指标评议表";
+			case BUSINESS:
+				return "商务指标评议表";
+			case TECHNOLOGY:
+				return "技术指标评议表";
+			default:
+				return null;
+		}
+	}
+	
+	@Override
+	public String getFileName() {
+		Optional<EvaluationFactorTypeEnum> evaluationFactorTypeEnum = evaluationStep.map(t -> t.getEvaluationParamByKey(EvaluationStepEnum.EVALUATION_FACTOR_TYPE)).map(EvaluationFactorTypeEnum.MAP::get);
+		if (!evaluationFactorTypeEnum.isPresent()) {
+			return null;
+		}
+		switch (evaluationFactorTypeEnum.get()) {
+			case COMPLIANCE:
+				return Messages.BidFileComments + "-" + "符合性" + ".xlsx";
+			case BUSINESS:
+				return Messages.BidFileComments + "-" + Messages.Business + ".xlsx";
+			case TECHNOLOGY:
+				return Messages.BidFileComments + "-" + Messages.Technology + ".xlsx";
+			default:
+				return null;
+		}
+	}
+	
+	@Override
+	public List<Supplier> getSupplierList() {
+		return factorClearBidContent.map(FactorClearBidContent::getSupplierList).orElseGet(ArrayList::new);
+	}
+	
+	@Override
+	public List<EvaluationFactor> getFactorList() {
+		return factorClearBidContent.map(FactorClearBidContent::getFactorList).orElseGet(ArrayList::new);
+	}
+	
+	@Override
+	public List<SupplierEvaluationFactor> getSupplierEvaluationFactorList() {
+		return factorClearBidContent.map(FactorClearBidContent::getSupplierEvaluationFactorList).orElseGet(ArrayList::new);
+	}
+
+	@Override
+	public String getContent(SupplierEvaluationFactor supplierEvaluationFactor) {
+		return supplierEvaluationFactor.getOpinion();
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidFileHandler.java b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidFileHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..f563fb27f361ec6a0220651d4e34ebdc64f46149
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/handler/FactorClearBidFileHandler.java
@@ -0,0 +1,85 @@
+package com.gx.obe.struct.handler;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+
+import org.eclipse.swt.core.MessageDialog;
+import org.eclipse.swt.core.utils.FileDialogUtils;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+import com.gx.obe.common.file.utils.FileUtils;
+import com.gx.obe.common.widget.shell.ProgressMessageDialog;
+import com.gx.obe.components.core.enumeration.EvaluationFactorEnum;
+import com.gx.obe.components.core.global.Global;
+import com.gx.obe.message.Messages;
+import com.gx.obe.util.utils.RuntimeUtils;
+import com.gx.obe.util.utils.StringUtils;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+
+public class FactorClearBidFileHandler {
+	
+	private Shell parentShell;
+	private TenderProjectEntity tenderProject;
+	
+	public FactorClearBidFileHandler(Shell parentShell, TenderProjectEntity tenderProject) {
+		this.parentShell = parentShell;
+		this.tenderProject = tenderProject;
+	}
+	
+	public void export() {
+		String directorySavePath = FileDialogUtils.getDirectorySavePath(Messages.Tips_selectExportDic, "[" + tenderProject.getTenderNo() + "]" + tenderProject.getTenderName());
+		if (StringUtils.isEmpty(directorySavePath)) {
+			return;
+		}
+		
+		String saveDir = directorySavePath + "[" + FileUtils.filterFileName(tenderProject.getTenderNo()) + "]" + "指标清标文件";
+		
+		ProgressMessageDialog messageDialog = new ProgressMessageDialog(parentShell, false, -1, null);
+		messageDialog.setTitle("导出指标清标文件");
+		
+		BiConsumer<String, Integer> message = (msg, flag) -> Display.getDefault().syncExec(() -> messageDialog.message(msg, flag));
+		Consumer<Boolean> finish = t -> Display.getDefault().syncExec(() -> messageDialog.finish(t));
+		
+		new Thread(() -> {
+			message.accept("开始导出指标清标文件!", 0);
+			
+			try {
+				Map<String, Object> scoreDateMap = new HashMap<>();
+				scoreDateMap.put("factorClearBidContent", new FactorClearBidContentFactory(tenderProject.getId()).create(EvaluationFactorEnum.AUDIT_SCORE));
+				Global.EXCEL_REPORT.generate(tenderProject, "FactorClearBidContent.xlsx", saveDir, scoreDateMap).waitOrGet();
+			} catch (Exception e1) {
+				message.accept("打分清标意见表生成失败!", -1);
+			}
+//			try {
+//				Global.EXCEL_REPORT.generate(tenderProject, "ProjectManagerPerformanceDataSet.xlsx", saveDir, null).waitOrGet();
+//			} catch (Exception e1) {
+//				message.accept("项目经理业绩表生成失败!", -1);
+//			}
+//			try {
+//				Global.EXCEL_REPORT.generate(tenderProject, "EnterprisePerformanceDataSet.xlsx", saveDir, null).waitOrGet();
+//			} catch (Exception e1) {
+//				message.accept("企业业绩表生成失败!", -1);
+//			}
+			
+			message.accept("完成导出指标清标文件!", 0);
+			
+			if (messageDialog.getErrorMessagesSize() != 0) {
+				finish.accept(false);
+				return;
+			}
+			
+			finish.accept(true);
+			Display.getDefault().syncExec(() -> {
+				if (MessageDialog.openConfirm(parentShell, Messages.Button_openDirectory, Messages.Tips_exportAndOpenDirectory, new String[] { Messages.Button_open, Messages.Button_close })) {
+					System.out.println(saveDir);
+					RuntimeUtils.openDirector(saveDir);
+				}
+			});
+		}).start();
+		messageDialog.open();
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/handler/RelChapterTypeHandler.java b/com.gx.obe.struct/src/com/gx/obe/struct/handler/RelChapterTypeHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..357ec7012f68f68ffc3e06f0aa326380dad1229d
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/handler/RelChapterTypeHandler.java
@@ -0,0 +1,42 @@
+package com.gx.obe.struct.handler;
+
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class RelChapterTypeHandler {
+	
+	private final String relChapterType;
+	
+	private final String mark;
+	
+	private final boolean hasMark;
+	
+	private static final Set<String> SET = Stream.of("00", "01", "02").collect(Collectors.toSet());
+	
+	public RelChapterTypeHandler(String relChapterType) {
+		Optional<String> mark = SET.stream().map("_"::concat).filter(relChapterType::endsWith).findAny();
+		this.hasMark = mark.isPresent();
+		if (this.hasMark) {
+			this.mark = mark.get().substring(1);
+			this.relChapterType = relChapterType.substring(0, relChapterType.length() - mark.get().length());
+		} else {
+			this.mark = null;
+			this.relChapterType = relChapterType;
+		}
+	}
+	
+	public String getRelChapterType() {
+		return relChapterType;
+	}
+	
+	public String getMark() {
+		return mark;
+	}
+	
+	public boolean isHasMark() {
+		return hasMark;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/inters/IFactorClearBidContent.java b/com.gx.obe.struct/src/com/gx/obe/struct/inters/IFactorClearBidContent.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7ca422e11437a8bcedade175c5aa3dcb32ba7f0
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/inters/IFactorClearBidContent.java
@@ -0,0 +1,23 @@
+package com.gx.obe.struct.inters;
+
+import java.util.List;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+
+public interface IFactorClearBidContent {
+	
+	String getTableName();
+	
+	String getFileName();
+	
+	List<Supplier> getSupplierList();
+	
+	List<EvaluationFactor> getFactorList();
+	
+	List<SupplierEvaluationFactor> getSupplierEvaluationFactorList();
+	
+	String getContent(SupplierEvaluationFactor supplierEvaluationFactor);
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/inters/IModelData.java b/com.gx.obe.struct/src/com/gx/obe/struct/inters/IModelData.java
new file mode 100644
index 0000000000000000000000000000000000000000..6a22806329ddf0085451b4d8160bd9fdf7a52305
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/inters/IModelData.java
@@ -0,0 +1,25 @@
+package com.gx.obe.struct.inters;
+
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.bind.view.Write;
+import com.gx.obe.struct.beans.ModelData;
+
+public abstract class IModelData {
+	
+	protected final Prop<String> supplierId = new Prop<>();
+	
+	protected final Prop<Integer> count = new Prop<>();
+	
+	public IModelData() {
+		init();
+	}
+	
+	protected abstract void init();
+	
+	public abstract void refresh(ModelData modelData);
+
+	public void setCountWrite(Write<Integer> countConsumer) {
+		count.bind(countConsumer);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/inters/IModelDataDetail.java b/com.gx.obe.struct/src/com/gx/obe/struct/inters/IModelDataDetail.java
new file mode 100644
index 0000000000000000000000000000000000000000..2414b193d2c13121b7a2ecbc8d90daebbf6d0584
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/inters/IModelDataDetail.java
@@ -0,0 +1,19 @@
+package com.gx.obe.struct.inters;
+
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.eclipse.swt.widgets.Composite;
+
+public interface IModelDataDetail {
+	
+	void refreshTitle(String string);
+	
+	void addBasicSubpage(Function<Composite, Composite> initSub);
+	
+	void addSubpage(String name, Function<Composite, Composite> initSub);
+	
+	<T> void addAttachmentSubpage(Consumer<BiConsumer<String, String>> supplierIdAndBusinessIdConsumer);
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/listener/CellDoubleClickListener.java b/com.gx.obe.struct/src/com/gx/obe/struct/listener/CellDoubleClickListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..c67dbec52f548ea61e4e2e07e03767b5a737d709
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/listener/CellDoubleClickListener.java
@@ -0,0 +1,8 @@
+package com.gx.obe.struct.listener;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+
+public interface CellDoubleClickListener {
+	void cellDoubleClicked(EvaluationFactor evaluationFactor, SupplierEvaluationFactor supplierEvaluationFactor);
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/listener/EditOpinionListener.java b/com.gx.obe.struct/src/com/gx/obe/struct/listener/EditOpinionListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..1db83351d1adc84f92564a95c0e741f2a958ca69
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/listener/EditOpinionListener.java
@@ -0,0 +1,6 @@
+package com.gx.obe.struct.listener;
+
+public interface EditOpinionListener {
+	public void editOpinion(String opinion, String modifyReason);
+	public void cancle();
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/listener/GoBackListener.java b/com.gx.obe.struct/src/com/gx/obe/struct/listener/GoBackListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..48e45a5833c0633fb4341d46fd96d434cac39e6a
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/listener/GoBackListener.java
@@ -0,0 +1,5 @@
+package com.gx.obe.struct.listener;
+
+public interface GoBackListener {
+	void goBackAction();
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/listener/ReturnListener.java b/com.gx.obe.struct/src/com/gx/obe/struct/listener/ReturnListener.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca65233c91d186a4c8e46213c75a8936f9018a45
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/listener/ReturnListener.java
@@ -0,0 +1,5 @@
+package com.gx.obe.struct.listener;
+
+public interface ReturnListener {
+	void returnAction();
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/parse/BidFileIndexTreeXmlParse.java b/com.gx.obe.struct/src/com/gx/obe/struct/parse/BidFileIndexTreeXmlParse.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9ebff2119c6a00e06979f9c5f26cc5013fb6df0
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/parse/BidFileIndexTreeXmlParse.java
@@ -0,0 +1,69 @@
+package com.gx.obe.struct.parse;
+
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.dom4j.Document;
+import org.dom4j.Element;
+
+import com.gx.obe.util.utils.ObjectUtils;
+import com.gx.obe.util.utils.XmlUtils;
+
+public class BidFileIndexTreeXmlParse {
+	
+	private static final String BID_FILE_INDEX_TREE = "BidFileIndexTree.xml";
+	
+	private String rootNodeFileName;
+	private int pageNumInGenerateFile;
+	
+	private String bidFilePath;
+	private String relChapterType;
+	
+	public BidFileIndexTreeXmlParse(String bidFilePath, String relChapterType) {
+		this.bidFilePath = bidFilePath;
+		this.relChapterType = relChapterType;
+		init();
+	}
+	
+	private void init() {
+		if (bidFilePath == null) {
+			return;
+		}
+		Document document = XmlUtils.getXmlDocument(bidFilePath + BID_FILE_INDEX_TREE);
+		if (document == null) {
+			return;
+		}
+		recursion(streamElement(document.getRootElement()));
+	}
+	
+	private boolean recursion(Stream<Element> stream) {
+		if (stream == null) return false;
+		return stream.anyMatch(e -> {
+			if (e.elementTextTrim("chapterType").equals(relChapterType)) {
+				pageNumInGenerateFile = ObjectUtils.getIntValue(e.elementTextTrim("pageNumInGenerateFile"), 0);
+//				if (e.elementTextTrim("isRootNode").equals("true")) rootNodeFileName = e.elementTextTrim("fileName");
+				pageNumInGenerateFile = 1;
+				rootNodeFileName = e.elementTextTrim("fileName");
+				return true;
+			}
+			boolean recursion = recursion(streamElement(e));
+			if (recursion && e.elementTextTrim("isRootNode").equals("true")) rootNodeFileName = e.elementTextTrim("fileName");
+			return recursion;
+		});
+	}
+	
+	private Stream<Element> streamElement(Element element) {
+		List<?> list = element.elements("fileItem");
+		if (list == null) return null;
+		return list.stream().map(t -> (Element) t);
+	}
+	
+	public String getRootNodeFilePath() {
+		return bidFilePath + rootNodeFileName;
+	}
+	
+	public int getPageNumInGenerateFile() {
+		return pageNumInGenerateFile;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/parse/SelfEvaluatesXmlParse.java b/com.gx.obe.struct/src/com/gx/obe/struct/parse/SelfEvaluatesXmlParse.java
new file mode 100644
index 0000000000000000000000000000000000000000..236dc574556a0b283c8142ddd9faee40352085de
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/parse/SelfEvaluatesXmlParse.java
@@ -0,0 +1,138 @@
+package com.gx.obe.struct.parse;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.dom4j.Element;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.struct.ElementClass;
+import com.gx.obe.struct.StructBusinessTypeEnum;
+import com.gx.obe.struct.beans.ParamValueDO;
+import com.gx.obe.struct.beans.SelfEvalParamsDO;
+import com.gx.obe.struct.value_list.CreditGrade;
+import com.gx.obe.struct.value_list.Finance;
+import com.gx.obe.struct.value_list.ParamValues;
+import com.gx.obe.struct.value_list.Performance;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+
+/**
+ * @Description: SelfEvaluates.xml文件解析
+ * @author chenxw
+ */
+public class SelfEvaluatesXmlParse {
+	
+	private final SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	
+	private final String tenderId;
+	/**
+	 * 
+	 * 
+	 */
+	private final Map<String, Map<String, SupplierEvaluationFactor>> mapByFactorCodeBySupplierId;
+	
+	/**
+	 * @author chenxw
+	 * @param tenderId
+	 */
+	public SelfEvaluatesXmlParse(String tenderId) {
+		this.tenderId = tenderId;
+		this.mapByFactorCodeBySupplierId = initMapByFactorCodeBySupplierId();
+	}
+	
+	/**
+	 * @Description: 初始化
+	 * @author chenxw
+	 * @return
+	 */
+	private Map<String, Map<String, SupplierEvaluationFactor>> initMapByFactorCodeBySupplierId() {
+		List<SupplierEvaluationFactor> supplierEvaluationFactorList = supplierEvaluationFactorService.getEntityListByTenderId(tenderId);
+		if (CollectionUtils.isNull(supplierEvaluationFactorList)) return new HashMap<>();
+		return supplierEvaluationFactorList.stream().collect(Collectors.groupingBy(SupplierEvaluationFactor::getSupplierId, Collectors.toMap(SupplierEvaluationFactor::getFactorCode, t -> t, (a, b) -> a)));
+	}
+	
+	/**
+	 * @Description: 解析
+	 * @author chenxw
+	 * @param supplierId
+	 * @param element
+	 */
+	public void parse(String supplierId, Element element) {
+		Map<String, SupplierEvaluationFactor> mapByFactorCode = mapByFactorCodeBySupplierId.computeIfAbsent(supplierId, $ -> new HashMap<>());
+		List<?> elements = element.elements();
+		elements.stream().map(t -> (Element) t).forEach(t -> {
+			SupplierEvaluationFactor supplierEvaluationFactor = mapByFactorCode.computeIfAbsent(t.elementTextTrim("evalFactorId"), evalFactorCode -> {
+				SupplierEvaluationFactor factor = new SupplierEvaluationFactor();
+				factor.setTenderId(tenderId);
+				factor.setSupplierId(supplierId);
+				factor.setFactorCode(evalFactorCode);
+				getSelfItemData(factor, t);
+				return factor;
+			});
+			String value = t.elementTextTrim("selfEvaluateValue");
+			supplierEvaluationFactor.setOpinion(value);
+			supplierEvaluationFactor.setFactorResponse(value);
+			
+			Element paramValueListElement = t.element("paramValueList");
+			if(null != paramValueListElement && paramValueListElement.elements().size() > 0) {
+				List<Element> paramValueElementList = paramValueListElement.elements();
+				if(null != paramValueElementList && paramValueElementList.size() > 0) {
+					SelfEvalParamsDO selfEvalParamsDO = new SelfEvalParamsDO();
+					
+					for(Element paramValueElement : paramValueElementList) {
+						ParamValueDO paramValueDO = new ParamValueDO();
+						paramValueDO.setDataCode(paramValueElement.elementTextTrim("dataCode"));
+						paramValueDO.setDataType(paramValueElement.elementTextTrim("dataType"));
+						paramValueDO.setDataValue(paramValueElement.elementTextTrim("dataValue"));
+						selfEvalParamsDO.addParamValue(paramValueDO);
+					}
+					supplierEvaluationFactor.setParamValues(selfEvalParamsDO.toJson());
+				}
+			}
+			
+		});
+	}
+	private void getSelfItemData(SupplierEvaluationFactor factor, Element t) {
+		String relChapterType = t.elementTextTrim("relChapterType");
+		Element valueList = t.element("valueList");
+		if(null != valueList) {
+			// 主营利润率
+			if(StructBusinessTypeEnum.EQ_PROFIT_RATIO.getKey().equals(relChapterType)) {
+				List<Finance> financeList= ElementClass.of(Finance.class).createList(valueList);
+				String financeListJsonStr = JsonUtil.jacksonObjectToStr(financeList);
+				factor.setFinance(financeListJsonStr);
+//				供货业绩(物资)
+			}else if(StructBusinessTypeEnum.EQ_ACHIEVEMENTS.getKey().equals(relChapterType)) {
+				List<Performance> performanceList= ElementClass.of(Performance.class).createList(valueList);
+				String performanceListJsonStr = JsonUtil.jacksonObjectToStr(performanceList);
+				factor.setPerformance(performanceListJsonStr);
+//				资信等级 EQ_Qualification_ZXDJ
+			}else if(StructBusinessTypeEnum.EQ_QUALIFICATION_ZXDJ.getKey().equals(relChapterType)) {
+				List<CreditGrade> creditGradeList= ElementClass.of(CreditGrade.class).createList(valueList);
+				String creditGradeListJsonStr = JsonUtil.jacksonObjectToStr(creditGradeList);
+				factor.setCreditGrade(creditGradeListJsonStr);
+			}else {
+				List<ParamValues> paramValuesList= ElementClass.of(ParamValues.class).createList(valueList);
+				String paramValuesListJsonStr = JsonUtil.jacksonObjectToStr(paramValuesList);
+				factor.setParamValues(paramValuesListJsonStr);
+			}
+		}
+	}
+
+	/**
+	 * @Description: 保存
+	 * @author chenxw
+	 * @return
+	 */
+	public boolean save() {
+		List<SupplierEvaluationFactor> supplierEvaluationFactorList = mapByFactorCodeBySupplierId.values().stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toList());
+		if (supplierEvaluationFactorList.isEmpty()) return true;
+		return supplierEvaluationFactorService.batchSaveOrUpdate(supplierEvaluationFactorList, new String[] { "opinion", "factorResponse", "paramValues" }) > 0;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/AttachmentFileService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/AttachmentFileService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ad81b50a0c32ffd0173cde82b1193ecf9be84c9
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/AttachmentFileService.java
@@ -0,0 +1,30 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.AttachmentFile;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+/**
+ * @Description:
+ * @author chenxw
+ */
+public class AttachmentFileService {
+	
+	private static final String URL = "obeAttachmentFile";
+	
+	/**
+	 * @Description: 获取附件列表
+	 * @author chenxw
+	 * @param businessId
+	 * @return
+	 */
+	public List<AttachmentFile> getAttachmentFileList(String businessId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("businessId", businessId);
+		return ObeHttpUtils.getList(URL.concat("/getAttachmentFileList"), param, AttachmentFile.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/BidderInfoService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/BidderInfoService.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc6ad9b8c40a05873333f02df95dab9c4be3d8bf
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/BidderInfoService.java
@@ -0,0 +1,32 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.BidderBasicInfo;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+/**
+ * @Description:
+ * @author chenxw
+ */
+public class BidderInfoService {
+	
+	private static final String URL = "obeBidderBasicInfo";
+	
+	/**
+	 * @Description: 获取投标人基本情况列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @return 
+	 */
+	public List<BidderBasicInfo> getBidderBasicInfoList(String tenderId, String modelDataId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("modelDataId", modelDataId);
+		return ObeHttpUtils.getList(URL.concat("/getBidderBasicInfoList"), param, BidderBasicInfo.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/BusinessLicenseService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/BusinessLicenseService.java
new file mode 100644
index 0000000000000000000000000000000000000000..d3cc2035cd1a275ddd2ab62110717b18a1a8ff91
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/BusinessLicenseService.java
@@ -0,0 +1,28 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.BusinessLicense;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+public class BusinessLicenseService {
+	
+	private static final String URL = "obeBusinessLicense";
+	
+	/**
+	 * @Description: 获取营业执照列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @return
+	 */
+	public List<BusinessLicense> getBusinessLicenseList(String tenderId, String modelDataId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("modelDataId", modelDataId);
+		return ObeHttpUtils.getList(URL.concat("/getBusinessLicenseList"), param, BusinessLicense.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/CertificateService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/CertificateService.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd73a6abae54d6c0a221916ea73263e9c913072a
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/CertificateService.java
@@ -0,0 +1,30 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.Certificate;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+/**
+ * @Description:
+ * @author chenxw
+ */
+public class CertificateService {
+	
+	private static final String URL = "obeCertificate";
+	
+	/**
+	 * @Description: 获取证书列表
+	 * @author chenxw
+	 * @param projectLeaderId
+	 * @return 
+	 */
+	public List<Certificate> getCertificateList(String projectLeaderId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("projectLeaderId", projectLeaderId);
+		return ObeHttpUtils.getList(URL.concat("/getCertificateList"), param, Certificate.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/EvaluationContentService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/EvaluationContentService.java
new file mode 100644
index 0000000000000000000000000000000000000000..e7a6adea788bc678a21905c5d42aecc6575ca358
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/EvaluationContentService.java
@@ -0,0 +1,76 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.StructDateInfo;
+import com.gx.obe.web.entity.Result.RequestBody;
+import com.gx.obe.web.entity.evaluation.EvaluationContent;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+public class EvaluationContentService {
+	
+	private static final String URL = "obeEvaluationContent";
+	
+	/**
+	 * @Description: 获取评审内容列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @return
+	 */
+	public List<EvaluationContent> getEvaluationContentList(String tenderId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		return ObeHttpUtils.getList(URL.concat("/getEvaluationContentList"), param, EvaluationContent.class);
+	}
+	
+	/**
+	 * @Description: 根据指标编号获取评审内容列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param factorCode
+	 * @return
+	 */
+	public List<EvaluationContent> getEvaluationContentListByFactorCode(String tenderId, String factorCode) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("factorCode", factorCode);
+		return ObeHttpUtils.getList(URL.concat("/getEvaluationContentListByFactorCode"), param, EvaluationContent.class);
+	}
+	
+	/**
+	 * @Description: 清空结构化信息数据
+	 * @author chenxw
+	 * @param tenderId
+	 * @return
+	 */
+	public boolean deleteStructDateInfo(String tenderId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		return ObeHttpUtils.getBoolean(URL.concat("/deleteStructDateInfo"), param);
+	}
+	
+	/**
+	 * @Description: 保存结构化信息数据
+	 * @author chenxw
+	 * @param structDateInfo
+	 */
+	public boolean saveStructDateInfo(StructDateInfo structDateInfo) {
+		return ObeHttpUtils.post(URL.concat("/saveStructDateInfo"), structDateInfo);
+	}
+	
+	/**
+	 * @Description: 清空并保存结构化信息数据
+	 * @author chenxw
+	 * @param tenderId
+	 * @param structDateInfo
+	 * @return
+	 */
+	public boolean deleteOrSaveStructDateInfo(String tenderId, StructDateInfo structDateInfo) {
+		RequestBody<StructDateInfo> requestBody = new RequestBody<StructDateInfo>(structDateInfo);
+		requestBody.setParam("tenderId", tenderId);
+		return ObeHttpUtils.post(URL.concat("/deleteOrSaveStructDateInfo"), requestBody);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/FinanceService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/FinanceService.java
new file mode 100644
index 0000000000000000000000000000000000000000..1193a3c0696fb69028796f54c7c4246bad333b1a
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/FinanceService.java
@@ -0,0 +1,28 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.Finance;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+public class FinanceService {
+	
+	private static final String URL = "obeFinance";
+	
+	/**
+	 * @Description: 获取财务状况列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @return
+	 */
+	public List<Finance> getFinanceList(String tenderId, String modelDataId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("modelDataId", modelDataId);
+		return ObeHttpUtils.getList(URL.concat("/getFinanceList"), param, Finance.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/ModelDataService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/ModelDataService.java
new file mode 100644
index 0000000000000000000000000000000000000000..eed44b052e63945cab92544b0ef4a4b20e459d43
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/ModelDataService.java
@@ -0,0 +1,31 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.ModelData;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+public class ModelDataService {
+	
+	private static final String URL = "obeModelData";
+	
+	/**
+	 * @Description: 获取对象结构化数据
+	 * @author chenxw
+	 * @param tenderId
+	 * @param supplierId
+	 * @param relChapterType
+	 * @param dataCode
+	 * @return
+	 */
+	public ModelData getModelData(String tenderId, String supplierId, String relChapterType, String dataCode) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("supplierId", supplierId);
+		param.put("relChapterType", relChapterType);
+		param.put("dataCode", dataCode);
+		return ObeHttpUtils.getOne(URL.concat("/getModelData"), param, ModelData.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/PerformanceService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/PerformanceService.java
new file mode 100644
index 0000000000000000000000000000000000000000..c703388b6bcbeb001fc2a4c4a7ce60ce28ea82de
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/PerformanceService.java
@@ -0,0 +1,28 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.Performance;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+public class PerformanceService {
+	
+	private static final String URL = "obePerformance";
+	
+	/**
+	 * @Description: 获取业绩列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @return
+	 */
+	public List<Performance> getPerformanceList(String tenderId, String modelDataId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("modelDataId", modelDataId);
+		return ObeHttpUtils.getList(URL.concat("/getPerformanceList"), param, Performance.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/ProjectLeaderService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/ProjectLeaderService.java
new file mode 100644
index 0000000000000000000000000000000000000000..b46bca07333d745344aee749d85166789495292f
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/ProjectLeaderService.java
@@ -0,0 +1,32 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.ProjectLeader;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+/**
+ * @Description:
+ * @author chenxw
+ */
+public class ProjectLeaderService {
+	
+	private static final String URL = "obeProjectLeader";
+	
+	/**
+	 * @Description: 获取项目负责人列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @return
+	 */
+	public List<ProjectLeader> getProjectLeaderList(String tenderId, String modelDataId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("modelDataId", modelDataId);
+		return ObeHttpUtils.getList(URL.concat("/getProjectLeaderList"), param, ProjectLeader.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/QualificationService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/QualificationService.java
new file mode 100644
index 0000000000000000000000000000000000000000..59c74e196ab82baee59b5550073e40b7ef4f014b
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/QualificationService.java
@@ -0,0 +1,28 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.Qualification;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+public class QualificationService {
+	
+	private static final String URL = "obeQualification";
+	
+	/**
+	 * @Description: 获取证书列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @return
+	 */
+	public List<Qualification> getQualificationList(String tenderId, String modelDataId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("modelDataId", modelDataId);
+		return ObeHttpUtils.getList(URL.concat("/getQualificationList"), param, Qualification.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/TemplateTableService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/TemplateTableService.java
new file mode 100644
index 0000000000000000000000000000000000000000..c20df27b23d06131d159d031ad181674d28cbe9a
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/TemplateTableService.java
@@ -0,0 +1,29 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.TemplateTable;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+public class TemplateTableService {
+	
+	private static final String URL = "obeTemplateTable";
+	
+	/**
+	 * @Description: 获取小范本表格列表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param factorId
+	 * @return
+	 */
+	public List<TemplateTable> getTemplateTableList(String tenderId, String relChapterType, String dataCode) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("tenderId", tenderId);
+		param.put("relChapterType", relChapterType);
+		param.put("dataCode", dataCode);
+		return ObeHttpUtils.getList(URL.concat("/getTemplateTableList"), param, TemplateTable.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/service/WorkExperienceService.java b/com.gx.obe.struct/src/com/gx/obe/struct/service/WorkExperienceService.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7c3679c7846e09f7929f842eedbd2368b246c5e
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/service/WorkExperienceService.java
@@ -0,0 +1,30 @@
+package com.gx.obe.struct.service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.gx.obe.struct.beans.WorkExperience;
+import com.gx.obe.web.utils.ObeHttpUtils;
+
+/**
+ * @Description:
+ * @author chenxw
+ */
+public class WorkExperienceService {
+	
+	private static final String URL = "obeWorkExperience";
+	
+	/**
+	 * @Description: 获取工作经历列表
+	 * @author chenxw
+	 * @param projectLeaderId
+	 * @return 
+	 */
+	public List<WorkExperience> getWorkExperienceList(String projectLeaderId) {
+		Map<String, Object> param = new HashMap<>();
+		param.put("projectLeaderId", projectLeaderId);
+		return ObeHttpUtils.getList(URL.concat("/getWorkExperienceList"), param, WorkExperience.class);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/thread/MyThread.java b/com.gx.obe.struct/src/com/gx/obe/struct/thread/MyThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5b3d60e31e570f2e4a0e515ca3d400213417ed4
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/thread/MyThread.java
@@ -0,0 +1,58 @@
+package com.gx.obe.struct.thread;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class MyThread implements Runnable{
+	public String message;
+	public Thread thread;
+	
+	private boolean isStop = false;
+//	public MyThread(){
+//		
+//	}
+//	public MyThread(Runnable runnable){
+//		
+//	}
+	private List<MyThread> joinThread;
+	public void start(){
+		thread = new Thread(this);
+		thread.start();
+	}
+	
+	public void stop(){
+		isStop = true;
+		thread = null;
+	}
+	
+	public void join(){
+		if(null != thread){
+			try {
+				thread.join();
+			} catch (InterruptedException e) {
+			}
+		}
+	}
+	
+	public void addJoinThread(MyThread thread){
+		if(null == joinThread){
+			joinThread = new ArrayList<MyThread>();
+		}
+		joinThread.add(thread);
+	}
+	
+	public void joinOtherThread(){
+		if(null != joinThread){
+			for(MyThread myRunnable : joinThread){
+				myRunnable.join();
+			}
+		}
+	}
+	public void setMessage(String message) {
+		this.message = message;
+	}
+	
+//	public static abstract class Runnable {
+//		public abstract void run();
+//	}
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingStructThread.java b/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingStructThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..185035a405c05b925fe6b3d18f7e4c01a73ba8ce
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingStructThread.java
@@ -0,0 +1,285 @@
+package com.gx.obe.struct.thread;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+import org.dom4j.Element;
+
+import com.gx.obe.common.widget.listener.ProgressMessageAdapter;
+import com.gx.obe.common.widget.listener.ProgressMessageListener;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.components.core.enumeration.CommonEnum;
+import com.gx.obe.struct.BidFileUtils;
+import com.gx.obe.struct.beans.ModelData;
+import com.gx.obe.struct.beans.StructDateInfo;
+import com.gx.obe.struct.enums.DataCategoryEnum;
+import com.gx.obe.struct.enums.ModelDataClassEnum;
+import com.gx.obe.struct.enums.ModelDataTypeEnum;
+import com.gx.obe.struct.handler.RelChapterTypeHandler;
+import com.gx.obe.struct.service.EvaluationContentService;
+import com.gx.obe.struct.utils.ParsingStructXmlUtils;
+import com.gx.obe.util.utils.UuidUtils;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.evaluation.EvaluationContent;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.service.SupplierService;
+
+/**
+ * @Description: 解析结构化数据线程
+ * @author chenxw
+ */
+public class ParsingStructThread implements Runnable {
+	
+	private final EvaluationContentService evaluationContentService = new EvaluationContentService();
+	private final SupplierService supplierService = new SupplierService();
+	private final StructDateInfo structDateInfo = new StructDateInfo();
+	private String tenderId;
+	private TenderProjectEntity tenderproject;
+	private ProgressMessageListener messageProgress;
+	/**
+	 * @author chenxw
+	 * @param tenderproject.getId()
+	 * @param callBack
+	 */
+	public ParsingStructThread(TenderProjectEntity tenderproject, ProgressMessageListener messageProgress) {
+		this.tenderproject = tenderproject;
+		this.messageProgress = messageProgress;
+	}
+	
+	@Override
+	public void run() {
+		this.tenderId = tenderproject.getId();
+		parsingStruct();
+		messageProgress.finish(messageProgress.getErrorMessagesSize() == 0);
+	}
+	
+	/**
+	 * @Description: 解析结构化数据
+	 * @author chenxw 
+	 */
+	private void parsingStruct() {
+		//--------------------------------获取供应商列表--------------------------------------------------
+		
+		messageProgress.message("开始获取获取供应商列表...", 0);
+		Optional<List<Supplier>> supplierListQptional = Optional.ofNullable(supplierService.getOpenBidSuccessSupplier(tenderId)).filter(t -> !t.isEmpty());
+		if (!supplierListQptional.isPresent()) {
+			messageProgress.message("供应商列表获取失败!", -1);
+			return;
+		}
+		messageProgress.message("供应商列表获取成功!", 1);
+		
+		//--------------------------------解析供应商评议表数据--------------------------------------------------
+		
+//		ParsingSupplierSelfOpinionThread parsingSupplierSelfOpinionThread = new ParsingSupplierSelfOpinionThread(tenderproject, supplierListQptional.get(),new ProgressMessageAdapter () {
+//			@Override
+//			public void message(String message, int flag) {
+//				messageProgress.message(message, flag);
+//			}
+//
+//			@Override
+//			public void finish(boolean flag) {
+//			}
+//		}) ;
+//		parsingSupplierSelfOpinionThread.start();
+//		parsingSupplierSelfOpinionThread.join();
+		
+		//--------------------------------解析供应商标书定位数据--------------------------------------------------
+		String isIntelligentScore = tenderproject.getEvaluationParamByKey("isIntelligentScore");
+		if(null != isIntelligentScore && CommonEnum.YES.equals(isIntelligentScore)) {		
+			ParsingSupplierRespItemThread parsingSupplierRespItemThread = new ParsingSupplierRespItemThread(tenderproject, supplierListQptional.get(),new ProgressMessageAdapter () {
+				@Override
+				public void message(String message, int flag) {
+					messageProgress.message(message, flag);
+				}
+	
+				@Override
+				public void finish(boolean flag) {
+				}
+			}) ;
+			parsingSupplierRespItemThread.start();
+			parsingSupplierRespItemThread.join();
+		}
+
+		//--------------------------------获取评审内容列表--------------------------------------------------
+		
+//		messageProgress.message("开始获取评审内容...", 0);
+		Optional<Map<String, Set<String>>> relChapterTypeListMapOptional = Optional.ofNullable(evaluationContentService.getEvaluationContentList(tenderId)).filter(t -> !t.isEmpty()).map(l -> {
+			return l.stream().collect(Collectors.groupingBy(EvaluationContent::getDataCategory, Collectors.mapping(EvaluationContent::getRelChapterType, Collectors.toSet())));
+		});
+		
+		Consumer<Set<String>> consumer = t -> {
+			t.add("CompletedAchievements");
+			t.add("OngoingAchievements");
+		};
+		relChapterTypeListMapOptional.map(t -> t.get(DataCategoryEnum.TDI.getKey())).ifPresent(consumer);
+		relChapterTypeListMapOptional.map(t -> t.get(DataCategoryEnum.TT.getKey())).ifPresent(consumer);
+		if (!relChapterTypeListMapOptional.isPresent()) {
+//			messageProgress.message("未获取到已绑定指标结构化内容!", -1);
+			return;
+		}
+//		messageCallBack.callBackMsg("开始获取评审内容!");
+//		messageCallBack.callBackMsg(true, "获取评审内容成功!");
+		
+		//--------------------------------解析投标结构化数据--------------------------------------------------
+		
+		messageProgress.message("开始解析结构化标书结构...", 0);
+		try {
+			relChapterTypeListMapOptional.map(m -> m.get(DataCategoryEnum.TT.getKey())).map(Set::parallelStream).ifPresent(s -> {
+				s.forEach(t -> {
+					ParsingStructXmlUtils.resolverTemplateTable(tenderId, t).ifPresent(structDateInfo.getTemplateTableList()::addAll);
+				});
+			});
+		} catch (Exception e) {
+			messageProgress.message("解析招标结构化数据失败,请检查是否下载招标文件!", -1);
+			return;
+		}
+		messageProgress.message("结构化标书结构解析成功!", 1);
+		
+		//--------------------------------解析投标结构化数据--------------------------------------------------
+		
+		messageProgress.message("开始解析投标结构化数据!", 1);
+		try {
+//			supplierListQptional.get().parallelStream().forEach(t -> parsingSupplierBidFileStruct(t, relChapterTypeListMapOptional.get(), Constants.getBidFilePath(tenderId, t.getId())));
+			supplierListQptional.get().stream().forEach(t -> {
+				messageProgress.message("正在解析[" + t.getSupplierName() +"]结构化数据...", 0);
+				parsingSupplierBidFileStruct(t, relChapterTypeListMapOptional.get(), Constants.getBidFilePath(tenderId, t.getId()));
+			});
+		} catch (Exception e) {
+			messageProgress.message("解析投标结构化数据失败!", -1);
+			return;
+		}
+		messageProgress.message("解析投标结构化数据成功!", 1);
+		
+		//--------------------------------保存结构化数据--------------------------------------------------
+		
+		messageProgress.message("开始保存结构化数据!", 0);
+		if (!evaluationContentService.deleteOrSaveStructDateInfo(tenderId, structDateInfo)) {
+			messageProgress.message("保存结构化数据失败!", -1);
+			return;
+		}
+		messageProgress.message("保存结构化数据成功!", 1);
+		
+		//--------------------------------end--------------------------------------------------
+		
+		messageProgress.message( "解析结构化数据结束!", 0);
+		messageProgress.message("---------------------------------", 0);
+	}
+	
+	/**
+	 * @Description: 解析对应供应商结构化数据
+	 * @author chenxw
+	 * @param supplier
+	 * @param relChapterTypeSetMap
+	 * @param bidFilePath
+	 */
+	private void parsingSupplierBidFileStruct(Supplier supplier, Map<String, Set<String>> relChapterTypeSetMap, String bidFilePath) {
+		//获取BidFileIndexTree.xml中fileItem列表
+		ParsingStructXmlUtils.resolverBidFileIndexTree(bidFilePath).filter(t -> !t.isEmpty()).ifPresent(el -> {
+			//解析小范本表单数据
+			Optional.ofNullable(relChapterTypeSetMap.get(DataCategoryEnum.TDI.getKey())).ifPresent(l -> structDateInfo.getTemplateDataItemList().addAll(l.stream().map(t -> {
+				return ParsingStructXmlUtils.resolverObeTemplateDataItem(tenderId, supplier.getId(), t, el, bidFilePath);
+			}).filter(Optional::isPresent).map(Optional::get).flatMap(List::stream).collect(Collectors.toList())));
+			//解析小范本表格数据
+			Optional.ofNullable(relChapterTypeSetMap.get(DataCategoryEnum.TT.getKey())).ifPresent(l -> structDateInfo.getTemplateTableList().addAll(l.stream().map(t -> {
+				return ParsingStructXmlUtils.resolverTemplateTable(tenderId, supplier.getId(), t, el, bidFilePath);
+			}).filter(Optional::isPresent).map(Optional::get).flatMap(List::stream).collect(Collectors.toList())));
+			//解析对象结构化数据
+			Optional.ofNullable(relChapterTypeSetMap.get(DataCategoryEnum.MD.getKey())).ifPresent(l -> l.stream().forEach(t -> parsingModelData(t, supplier, el, bidFilePath)));
+		});
+	}
+	
+	/**
+	 * @Description: 解析对应评审内容结构化数据
+	 * @author chenxw
+	 * @param evaluationContent
+	 * @param supplier
+	 * @param fileItemElementList
+	 * @param bidFilePath
+	 */
+	private void parsingModelData(String relChapterType, Supplier supplier, List<Element> fileItemElementList, String bidFilePath) {
+		//获取结构化数据xml文件地址
+		RelChapterTypeHandler handler = new RelChapterTypeHandler(relChapterType);
+		
+		Optional<ModelDataTypeEnum> modelDataTypeEnum = Optional.of(handler.getRelChapterType()).map(ModelDataTypeEnum.MAP::get);
+		
+		fileItemElementList.stream().filter(t -> {
+			return handler.getRelChapterType().equals(t.elementTextTrim("chapterType"));
+		}).findAny().map(this::getBidFileName).filter(Optional::isPresent).map(Optional::get).map(bidFilePath::concat).ifPresent(xmlFilePath -> {
+			ModelData modelData = initModelData(supplier.getId(), modelDataTypeEnum.map(ModelDataTypeEnum.EQ_ProjectLeader::equals).orElse(false) ? handler.getRelChapterType() : relChapterType);
+			structDateInfo.getModelDataList().add(modelData);
+			modelDataTypeEnum.map(ModelDataTypeEnum::getClassEnum).ifPresent(t -> parsingModelDataDetail(t, modelData.getId(), xmlFilePath, handler.getMark()));
+		});
+	}
+	
+	/**
+	 * @Description: 获得投标文件文件名
+	 * @author chenxw
+	 * @param fileItem
+	 * @param isEnc
+	 * @return
+	 */
+	public Optional<String> getBidFileName(Element fileItemElement) {
+		Optional<Element> fileItem = Optional.ofNullable(fileItemElement);
+		return BidFileUtils.getBidFileName(fileItem.map(t -> {
+			return t.elementText("fileName");
+		}).orElse(null), fileItem.map(t -> {
+			return t.elementText("fileId");
+		}).orElse(null));
+	}
+	
+	/**
+	 * @Description: 解析对象结构化数据明细
+	 * @author chenxw
+	 * @param modelDataEnum
+	 * @param modelDataId
+	 * @param xmlFilePath
+	 * @param string 
+	 */
+	private void parsingModelDataDetail(ModelDataClassEnum modelDataEnum, String modelDataId, String xmlFilePath, String mark) {
+		Consumer<ParsingStructXmlUtils.AttachmentFileOperation> consumer = t -> ParsingStructXmlUtils.resolverAttachmentFile(t).ifPresent(structDateInfo.getAttachmentFileList()::addAll);
+		switch (modelDataEnum) {
+			case BusinessLicense:
+				ParsingStructXmlUtils.resolverBusinessLicense(tenderId, modelDataId, xmlFilePath, consumer).ifPresent(structDateInfo.getBusinessLicenseList()::addAll);
+				break;
+			case BidderInfo:
+				ParsingStructXmlUtils.resolverBidderBasicInfo(tenderId, modelDataId, xmlFilePath, consumer).ifPresent(structDateInfo.getBidderBasicInfoList()::addAll);
+				break;
+			case Finance:
+				ParsingStructXmlUtils.resolverFinance(tenderId, modelDataId, xmlFilePath, consumer).ifPresent(structDateInfo.getFinanceList()::addAll);
+				break;
+			case Performance:
+				ParsingStructXmlUtils.resolverPerformance(tenderId, modelDataId, xmlFilePath, consumer, mark).ifPresent(structDateInfo.getPerformanceList()::addAll);
+				break;
+			case ProjectLeader:
+				ParsingStructXmlUtils.resolverProjectLeader(tenderId, modelDataId, xmlFilePath, consumer).ifPresent(structDateInfo.getProjectLeaderList()::addAll);
+				break;
+			case Qualification:
+				ParsingStructXmlUtils.resolverQualification(tenderId, modelDataId, xmlFilePath, consumer).ifPresent(structDateInfo.getQualificationList()::addAll);
+				break;
+			default:
+				break;
+		}
+	}
+	
+	/**
+	 * @Description: 初始化对象结构化数据
+	 * @author chenxw
+	 * @param supplierId
+	 * @param evaluationContent
+	 * @return
+	 */
+	private ModelData initModelData(String supplierId, String relChapterType) {
+		ModelData modelData = new ModelData();
+		modelData.setId(UuidUtils.getUUID());
+		modelData.setTenderId(tenderId);
+		modelData.setSupplierId(supplierId);
+		modelData.setRelChapterType(relChapterType);
+		modelData.setDataCode(relChapterType);
+		return modelData;
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingSupplierRespItemThread.java b/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingSupplierRespItemThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..61ccf173532387b97691b5cfebe990a2d20e9f76
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingSupplierRespItemThread.java
@@ -0,0 +1,129 @@
+package com.gx.obe.struct.thread;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang.StringUtils;
+import org.dom4j.Element;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.common.widget.listener.ProgressMessageListener;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.struct.beans.RespItemDO;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.util.utils.XmlUtils;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+
+public class ParsingSupplierRespItemThread extends MyThread{
+
+	
+	
+	private TenderProjectEntity tenderproject;
+	private List<Supplier> supplierList;
+	private SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	private Map<String, Map<String, SupplierEvaluationFactor>> mapByFactorCodeBySupplierId;
+	private ProgressMessageListener messageProgress;
+	
+	public ParsingSupplierRespItemThread(TenderProjectEntity tenderproject, List<Supplier> supplierList, ProgressMessageListener messageProgress) {
+		this.tenderproject = tenderproject;
+		this.supplierList = supplierList;
+		this.messageProgress = messageProgress;
+	}
+	
+	public void run() {
+		messageProgress.message("正在解析标书定位...", 0);
+		this.mapByFactorCodeBySupplierId = initMapByFactorCodeBySupplierId();
+		int count = 0;
+		if(null != supplierList && supplierList.size() > 0) {
+			for(Supplier supplier : supplierList) {
+				if(parsingSupplierRespItem(supplier)) {
+					count ++;
+				}
+			}
+		}
+		messageProgress.message("标书定位解析结束!", count > 0 ? 1 : -1);
+		messageProgress.finish(count > 0);
+	
+	}
+	
+	/**
+	 * @Description: 初始化
+	 * @author chenxw
+	 * @return
+	 */
+	private Map<String, Map<String, SupplierEvaluationFactor>> initMapByFactorCodeBySupplierId() {
+		List<SupplierEvaluationFactor> supplierEvaluationFactorList = supplierEvaluationFactorService.getEntityListByTenderId(tenderproject.getId());
+		if (CollectionUtils.isNull(supplierEvaluationFactorList)) return new HashMap<>();
+		return supplierEvaluationFactorList.stream().collect(Collectors.groupingBy(SupplierEvaluationFactor::getSupplierId, Collectors.toMap(SupplierEvaluationFactor::getFactorCode, t -> t, (a, b) -> a)));
+	}
+	
+	/**
+	 * @Description: 解析
+	 * @author chenxw
+	 * @param supplierId
+	 * @param element
+	 */
+	public boolean parsingSupplierRespItem(Supplier supplier) {
+		messageProgress.message("正在解析"+supplier.getSupplierName()+"标书定位...", 0);
+		File respItemFile = new File(Constants.getBidFilePath(tenderproject.getId(), supplier.getId()) + "RespItem.xml");
+		if(respItemFile.exists()) {
+			Element element = XmlUtils.getXmlDocument(respItemFile.getAbsolutePath()).getRootElement();
+			//TODO
+			List<?> elements = element.elements();
+			List<RespItemDO> respItemDOList = new ArrayList<>();
+			if(null != elements && elements.size() > 0) {
+				elements.stream().map(t -> (Element) t).forEach(t -> {
+					RespItemDO respItemDO = new RespItemDO();
+					respItemDO.setEvalFactorId(t.attributeValue("evalFactorId"));
+					respItemDO.setFileId(t.attributeValue("fileId"));
+					respItemDO.setFileName(t.attributeValue("fileName"));
+					respItemDO.setPageNumber(t.elementTextTrim("pageNumber"));
+					respItemDO.setEndPageNumber(t.elementTextTrim("endPageNumber"));
+					respItemDO.setName(t.elementTextTrim("name"));
+					respItemDOList.add(respItemDO);
+				});
+			}
+			Map<String, SupplierEvaluationFactor> mapByFactorCode = mapByFactorCodeBySupplierId.get(supplier.getId());
+			Map<String, List<RespItemDO>> respItemMap = respItemDOList.stream().collect(Collectors.groupingBy(RespItemDO::getEvalFactorId));
+			if(null != mapByFactorCode && null != respItemMap) {
+				for(String evalFactorId : respItemMap.keySet()) {
+					SupplierEvaluationFactor supplierEvaluationFactor = mapByFactorCode.get(evalFactorId);
+					if(null != supplierEvaluationFactor) {
+						supplierEvaluationFactor.setRespItemList(JsonUtil.jsonObjectToStr(respItemMap.get(evalFactorId)));
+						//页码拼接
+						List<String> pageList = respItemMap.get(evalFactorId).stream().map(RespItemDO::getPage).collect(Collectors.toList());
+						String pageNumber = StringUtils.join(pageList, "、");
+						supplierEvaluationFactor.setParam("pageNumber", pageNumber);
+					}
+				}
+			}
+		}else {
+			messageProgress.message("未找到"+supplier.getSupplierName()+"标书定位,请先下载标书或检查标书中是否提供了标书定位!", -1);
+			return false;
+		}
+		
+		if(null != mapByFactorCodeBySupplierId.get(supplier.getId()) && mapByFactorCodeBySupplierId.get(supplier.getId()).values().size() > 0) {
+			
+			List<SupplierEvaluationFactor> supplierEvaluationFactorList = mapByFactorCodeBySupplierId.get(supplier.getId()).values().stream().collect(Collectors.toList());
+			int count = supplierEvaluationFactorService.batchSaveOrUpdate(supplierEvaluationFactorList, new String[] { "respItemList", "computerParams"});
+			if(count > 0) {
+				messageProgress.message(supplier.getSupplierName()+"标书定位解析成功!", 1);
+				return true;
+			}
+		}
+		messageProgress.message(supplier.getSupplierName()+"标书定位解析失败!", -1);
+		return false;
+	}
+	
+
+	
+
+}
\ No newline at end of file
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingSupplierSelfOpinionThread.java b/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingSupplierSelfOpinionThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..c2f806037a5931c174f0b4cec3166309173ceb19
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/thread/ParsingSupplierSelfOpinionThread.java
@@ -0,0 +1,170 @@
+package com.gx.obe.struct.thread;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.dom4j.Element;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.common.widget.listener.ProgressMessageListener;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.evaluation.struct.enumeration.StructBusinessTypeEnum;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.struct.ElementClass;
+import com.gx.obe.struct.beans.ParamValueDO;
+import com.gx.obe.struct.beans.SelfEvalParamsDO;
+import com.gx.obe.struct.value_list.CreditGrade;
+import com.gx.obe.struct.value_list.Finance;
+import com.gx.obe.struct.value_list.ParamValues;
+import com.gx.obe.struct.value_list.Performance;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.util.utils.XmlUtils;
+import com.gx.obe.web.entity.Supplier;
+import com.gx.obe.web.entity.tender.TenderProjectEntity;
+import com.gx.obe.web.service.SupplierEvaluationFactorService;
+
+public class ParsingSupplierSelfOpinionThread extends MyThread{
+
+	
+	
+	private TenderProjectEntity tenderproject;
+	private List<Supplier> supplierList;
+	private SupplierEvaluationFactorService supplierEvaluationFactorService = new SupplierEvaluationFactorService();
+	private Map<String, Map<String, SupplierEvaluationFactor>> mapByFactorCodeBySupplierId;
+	private ProgressMessageListener messageProgress;
+	
+	public ParsingSupplierSelfOpinionThread(TenderProjectEntity tenderproject, List<Supplier> supplierList, ProgressMessageListener messageProgress) {
+		this.tenderproject = tenderproject;
+		this.supplierList = supplierList;
+		this.messageProgress = messageProgress;
+	}
+	
+	public void run() {
+		messageProgress.message("正在解析自我评议...", 0);
+		this.mapByFactorCodeBySupplierId = initMapByFactorCodeBySupplierId();
+		int count = 0;
+		if(null != supplierList && supplierList.size() > 0) {
+			for(Supplier supplier : supplierList) {
+				if(parsingSupplierSelfOpinion(supplier)) {
+					count ++;
+				}
+			}
+		}
+		messageProgress.message("自我评议解析结束!", count > 0 ? 1 : -1);
+		messageProgress.finish(count > 0);
+	
+	}
+	
+	/**
+	 * @Description: 初始化
+	 * @author chenxw
+	 * @return
+	 */
+	private Map<String, Map<String, SupplierEvaluationFactor>> initMapByFactorCodeBySupplierId() {
+		List<SupplierEvaluationFactor> supplierEvaluationFactorList = supplierEvaluationFactorService.getEntityListByTenderId(tenderproject.getId());
+		if (CollectionUtils.isNull(supplierEvaluationFactorList)) return new HashMap<>();
+		return supplierEvaluationFactorList.stream().collect(Collectors.groupingBy(SupplierEvaluationFactor::getSupplierId, Collectors.toMap(SupplierEvaluationFactor::getFactorCode, t -> t, (a, b) -> a)));
+	}
+	
+	/**
+	 * @Description: 解析
+	 * @author chenxw
+	 * @param supplierId
+	 * @param element
+	 */
+	public boolean parsingSupplierSelfOpinion(Supplier supplier) {
+		messageProgress.message("正在解析"+supplier.getSupplierName()+"自评意见...", 0);
+		File selfEvaluatesFile = new File(Constants.getBidFilePath(tenderproject.getId(), supplier.getId()) + "SelfEvaluates.xml");
+		if(selfEvaluatesFile.exists()) {
+			Element element = XmlUtils.getXmlDocument(selfEvaluatesFile.getAbsolutePath()).getRootElement();
+			Map<String, SupplierEvaluationFactor> mapByFactorCode = mapByFactorCodeBySupplierId.computeIfAbsent(supplier.getId(), $ -> new HashMap<>());
+			List<?> elements = element.elements();
+			elements.stream().map(t -> (Element) t).forEach(t -> {
+				SupplierEvaluationFactor supplierEvaluationFactor = mapByFactorCode.computeIfAbsent(t.elementTextTrim("evalFactorId"), evalFactorCode -> {
+					SupplierEvaluationFactor factor = new SupplierEvaluationFactor();
+					factor.setTenderId(tenderproject.getId());
+					factor.setSupplierId(supplier.getId());
+					factor.setFactorCode(evalFactorCode);
+					getSelfItemData(factor, t);
+					return factor;
+				});
+				String value = t.elementTextTrim("selfEvaluateValue");
+				supplierEvaluationFactor.setOpinion(value);
+				supplierEvaluationFactor.setFactorResponse(value);
+				Element paramValueListElement = t.element("paramValueList");
+				if(null != paramValueListElement && paramValueListElement.elements().size() > 0) {
+					List<Element> paramValueElementList = paramValueListElement.elements();
+					if(null != paramValueElementList && paramValueElementList.size() > 0) {
+						SelfEvalParamsDO selfEvalParamsDO = new SelfEvalParamsDO();
+						
+						for(Element paramValueElement : paramValueElementList) {
+							ParamValueDO paramValueDO = new ParamValueDO();
+							paramValueDO.setDataCode(paramValueElement.elementTextTrim("dataCode"));
+							paramValueDO.setDataType(paramValueElement.elementTextTrim("dataType"));
+							paramValueDO.setDataValue(paramValueElement.elementTextTrim("dataValue"));
+							selfEvalParamsDO.addParamValue(paramValueDO);
+						}
+						supplierEvaluationFactor.setParamValues(selfEvalParamsDO.toJson());
+					}
+				}
+			});
+		}else {
+			messageProgress.message("未找到"+supplier.getSupplierName()+"自评意见,请先下载标书或检查标书中是否提供了自评意见!", -1);
+			return false;
+		}
+		
+		if(null != mapByFactorCodeBySupplierId.get(supplier.getId()) && mapByFactorCodeBySupplierId.get(supplier.getId()).values().size() > 0) {
+			
+			List<SupplierEvaluationFactor> supplierEvaluationFactorList = mapByFactorCodeBySupplierId.get(supplier.getId()).values().stream().collect(Collectors.toList());
+			int count = supplierEvaluationFactorService.batchSaveOrUpdate(supplierEvaluationFactorList, new String[] { "opinion", "factorResponse", "paramValues" });
+			if(count > 0) {
+				messageProgress.message(supplier.getSupplierName()+"自评意见解析成功!", 1);
+				return true;
+			}
+		}
+		messageProgress.message(supplier.getSupplierName()+"自评意见解析失败!", -1);
+		return false;
+	}
+	private void getSelfItemData(SupplierEvaluationFactor factor, Element t) {
+		String relChapterType = t.elementTextTrim("relChapterType");
+		Element valueList = t.element("valueList");
+		if(null != valueList) {
+			// 主营利润率
+			if(StructBusinessTypeEnum.EQ_PROFIT_RATIO.getKey().equals(relChapterType)) {
+				List<Finance> financeList= ElementClass.of(Finance.class).createList(valueList);
+				String financeListJsonStr = JsonUtil.jacksonObjectToStr(financeList);
+				factor.setFinance(financeListJsonStr);
+//				供货业绩(物资)
+			}else if(StructBusinessTypeEnum.EQ_ACHIEVEMENTS.getKey().equals(relChapterType)) {
+				List<Performance> performanceList= ElementClass.of(Performance.class).createList(valueList);
+				String performanceListJsonStr = JsonUtil.jacksonObjectToStr(performanceList);
+				factor.setPerformance(performanceListJsonStr);
+//				资信等级 EQ_Qualification_ZXDJ
+			}else if(StructBusinessTypeEnum.EQ_QUALIFICATION_ZXDJ.getKey().equals(relChapterType)) {
+				List<CreditGrade> creditGradeList= ElementClass.of(CreditGrade.class).createList(valueList);
+				String creditGradeListJsonStr = JsonUtil.jacksonObjectToStr(creditGradeList);
+				factor.setCreditGrade(creditGradeListJsonStr);
+			}else {
+				List<ParamValues> paramValuesList= ElementClass.of(ParamValues.class).createList(valueList);
+				String paramValuesListJsonStr = JsonUtil.jacksonObjectToStr(paramValuesList);
+				factor.setParamValues(paramValuesListJsonStr);
+			}
+		}
+	}
+
+	/**
+	 * @Description: 保存
+	 * @author chenxw
+	 * @return
+	 */
+	public boolean save() {
+		List<SupplierEvaluationFactor> supplierEvaluationFactorList = mapByFactorCodeBySupplierId.values().stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toList());
+		if (supplierEvaluationFactorList.isEmpty()) return true;
+		return supplierEvaluationFactorService.batchSaveOrUpdate(supplierEvaluationFactorList, new String[] { "opinion", "factorResponse" }) > 0;
+	}
+
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/tree/EvaluationFactorTree.java b/com.gx.obe.struct/src/com/gx/obe/struct/tree/EvaluationFactorTree.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1548e879fc413556b525ea300ca09bc64837767
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/tree/EvaluationFactorTree.java
@@ -0,0 +1,71 @@
+package com.gx.obe.struct.tree;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import com.gx.obe.business.entity.SupplierEvaluationFactor;
+import com.gx.obe.component.tree.ITree;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.web.entity.evaluation.EvaluationFactor;
+
+public class EvaluationFactorTree implements ITree<EvaluationFactorTree> {
+	
+	private EvaluationFactor evaluationFactor;
+	private Map<String, SupplierEvaluationFactor> mapBySupplierId;
+	private Map<String, Map<String, SupplierEvaluationFactor>> mapBySupplierIdByFactorCode;
+	private Function<SupplierEvaluationFactor, String> mapper;
+	
+	public EvaluationFactorTree(EvaluationFactor evaluationFactor, Map<String, Map<String, SupplierEvaluationFactor>> mapBySupplierIdByFactorCode, Function<SupplierEvaluationFactor, String> mapper) {
+		this.evaluationFactor = Objects.requireNonNull(evaluationFactor);
+		this.mapBySupplierId = mapBySupplierIdByFactorCode.get(evaluationFactor.getFactorCode());
+		this.mapBySupplierIdByFactorCode = mapBySupplierIdByFactorCode;
+		if("对应页码".equals(evaluationFactor.getFactorName())) {
+			mapper = SupplierEvaluationFactor::getPageNumber;
+		}
+		this.mapper = mapper;
+	}
+	
+	@Override
+	public ITree<EvaluationFactorTree> getRoot() {
+		if (evaluationFactor.getParentFactor() == null) {
+			return null;
+		}
+		return new EvaluationFactorTree(evaluationFactor.getParentFactor(), mapBySupplierIdByFactorCode, mapper);
+	}
+	
+	@Override
+	public List<EvaluationFactorTree> getITrees() {
+		if (CollectionUtils.isNull(evaluationFactor.getChildFactorList())) {
+			return null;
+		}
+		return evaluationFactor.getChildFactorList().stream().map(t -> new EvaluationFactorTree(t, mapBySupplierIdByFactorCode, mapper)).collect(Collectors.toList());
+	}
+	
+	@Override
+	public String getName() {
+		return evaluationFactor.getFactorName();
+	}
+	
+	@Override
+	public String getKey() {
+		return evaluationFactor.getId();
+	}
+	
+	@Override
+	public String getValue(Object key) {
+		return Optional.ofNullable(mapBySupplierId).map(m -> m.get(key)).map(mapper).orElse("");
+	}
+	
+	public EvaluationFactor getEvaluationFactor() {
+		return evaluationFactor;
+	}
+	
+	public SupplierEvaluationFactor getSupplierEvaluationFactorByKey(Object key) {
+		return mapBySupplierId.get(key);
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/utils/ElementUtils.java b/com.gx.obe.struct/src/com/gx/obe/struct/utils/ElementUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..caaed6f959bbd02f14fe5c3b88f41a2f6f6ec8ce
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/utils/ElementUtils.java
@@ -0,0 +1,20 @@
+package com.gx.obe.struct.utils;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.dom4j.Element;
+
+public class ElementUtils {
+	
+	public static Function<Element, Stream<Element>> toStreamFun(String listName, String itemName) {
+		return e -> {
+			List<?> elements = Optional.ofNullable(e).map(t -> t.element(listName)).map(t -> t.elements(itemName)).orElse(null);
+			if (elements == null) return null;
+			return elements.stream().map(t -> (Element) t);
+		};
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/utils/ParsingStructXmlUtils.java b/com.gx.obe.struct/src/com/gx/obe/struct/utils/ParsingStructXmlUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..0db7d816a86a1010d99d108f2f527e065b894e9a
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/utils/ParsingStructXmlUtils.java
@@ -0,0 +1,807 @@
+package com.gx.obe.struct.utils;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+import org.dom4j.Document;
+import org.dom4j.Element;
+
+import com.gx.obe.bind.recursion.Recursions;
+import com.gx.obe.common.file.utils.ParsingXmlUtils;
+import com.gx.obe.components.core.Constants;
+import com.gx.obe.http.json.JsonUtil;
+import com.gx.obe.struct.BusinessNowTimeUtils;
+import com.gx.obe.struct.beans.AttachmentFile;
+import com.gx.obe.struct.beans.BidderBasicInfo;
+import com.gx.obe.struct.beans.BusinessLicense;
+import com.gx.obe.struct.beans.Certificate;
+import com.gx.obe.struct.beans.Finance;
+import com.gx.obe.struct.beans.Performance;
+import com.gx.obe.struct.beans.ProjectLeader;
+import com.gx.obe.struct.beans.Qualification;
+import com.gx.obe.struct.beans.TemplateDataItem;
+import com.gx.obe.struct.beans.TemplateTable;
+import com.gx.obe.struct.beans.WorkExperience;
+import com.gx.obe.util.utils.CollectionUtils;
+import com.gx.obe.util.utils.ObjectUtils;
+import com.gx.obe.util.utils.StringUtils;
+import com.gx.obe.util.utils.UuidUtils;
+import com.gx.obe.util.utils.XmlUtils;
+import com.gx.obe.web.entity.evaluation.EvaluationContent;
+
+/**
+ * @Description: 解析结构化xml文件工具类
+ * @author chenxw
+ */
+public class ParsingStructXmlUtils {
+	
+	private static final String BID_FILE_INDEX_TREE = "BidFileIndexTree.xml";
+	
+	private static final String TENDER_STRUCT = "TenderStruct.xml";
+	
+	private ParsingStructXmlUtils() {}
+	
+	private static Stream<Element> streamElement(List<?> list) {
+		return list.stream().map(t -> (Element) t);
+	}
+	
+	/**
+	 * @Description: 解析评审内容
+	 * @author chenxw
+	 * @param tenderId
+	 * @param factorCode
+	 * @param evaluationContentListElement
+	 * @return
+	 */
+	public static Optional<List<EvaluationContent>> resolverEvaluationContent(String tenderId, String factorCode, Element evaluationContentListElement) {
+		return Optional.ofNullable(evaluationContentListElement).map(t -> t.elements("evaluationContent")).map(l -> {
+			return streamElement(l).map(ParsingStructXmlUtils::initEvaluationContent).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setFactorCode(factorCode);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化评审内容
+	 * @author chenxw
+	 * @param evaluationContentElement
+	 * @return
+	 */
+	private static EvaluationContent initEvaluationContent(Element evaluationContentElement) {
+		EvaluationContent evaluationContent = new EvaluationContent();
+		evaluationContent.setId(UuidUtils.getUUID());
+		evaluationContent.setRelChapterType(evaluationContentElement.elementTextTrim("relChapterType"));
+		evaluationContent.setDataCategory(evaluationContentElement.elementTextTrim("dataCategory"));
+		evaluationContent.setDataCode(evaluationContentElement.elementTextTrim("dataCode"));
+		evaluationContent.setEvalRule(evaluationContentElement.elementTextTrim("evalRule"));
+		evaluationContent.setTenderStructName(evaluationContentElement.elementTextTrim("tenderStructName"));
+		evaluationContent.setEvalPointName(evaluationContentElement.elementTextTrim("evalPointName"));
+		try {
+			evaluationContent.setSortNo(Integer.valueOf(evaluationContentElement.elementTextTrim("Order")));
+		} catch (Exception e) {}
+		return evaluationContent;
+	}
+	
+	/**
+	 * @Description: 解析投标树形索引文件
+	 * @author chenxw
+	 * @param tenderId
+	 * @param supplierId
+	 * @return
+	 */
+	public static Optional<List<Element>> resolverBidFileIndexTree(String bidFilePath) {
+		return Optional.ofNullable(bidFilePath).map(t -> {
+			return t.concat(BID_FILE_INDEX_TREE);
+		}).map(XmlUtils::getXmlDocument).map(Document::getRootElement).map(Element::elements).map(l -> {
+			return streamElement(l).map(t -> {
+				List<Element> list = streamElement(t.elements()).collect(Collectors.toList());
+				resolverBidFileIndexTree(list);
+				return list;
+			}).flatMap(List::stream).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 递归解析投标树形索引文件
+	 * @author chenxw
+	 * @param fileItemElementList
+	 * @return
+	 */
+	private static void resolverBidFileIndexTree(List<Element> fileItemElementList) {
+		List<Element> childfileItemList = streamElement(fileItemElementList).flatMap(t -> streamElement(t.elements("fileItem"))).collect(Collectors.toList());
+		if (childfileItemList.isEmpty()) {
+			return;
+		}
+		resolverBidFileIndexTree(childfileItemList);
+		childfileItemList.stream().forEach(t -> fileItemElementList.add((Element) t.clone()));
+	}
+	
+	/**
+	 * @Description: 解析小范本表格
+	 * @author chenxw
+	 * @param tenderId
+	 * @param supplierId
+	 * @param relChapterType
+	 * @param fileItemElementList
+	 * @param bidFilePath
+	 * @return
+	 */
+	public static Optional<List<TemplateTable>> resolverTemplateTable(String tenderId, String supplierId, String relChapterType, List<Element> fileItemElementList, String bidFilePath) {
+		if (StringUtils.isEmpty(tenderId) || StringUtils.isEmpty(supplierId) || StringUtils.isEmpty(relChapterType) || CollectionUtils.isNull(fileItemElementList)) {
+			return Optional.empty();
+		}
+		return fileItemElementList.stream().filter(t -> {
+//			System.out.println(t.elementTextTrim("chapterType"));
+			return relChapterType.equals(t.elementTextTrim("chapterType"));
+		}).findAny().map(t -> t.element("tableList")).map(t -> t.elements("tableInfo")).map(l -> {
+			return streamElement(l).map(ParsingStructXmlUtils::initTemplateTable).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setSupplierId(supplierId);
+				t.setRelChapterType(relChapterType);
+				if (Stream.of("CompletedAchievements", "OngoingAchievements").anyMatch(Predicate.isEqual(relChapterType))) {
+					t.setDataCode(relChapterType);
+				}
+				Optional.ofNullable(bidFilePath).map(p -> p.concat(t.getXmlPath())).map(ParsingXmlUtils::parsingTableXML).map(JsonUtil::jsonObjectToStr).ifPresent(t::setTableInfo);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	public static Optional<List<TemplateTable>> resolverTemplateTable(String tenderId, String relChapterType) {
+		String biddingFilePath = Constants.getBiddingFilePath(tenderId);
+		Document document = XmlUtils.getXmlDocument(biddingFilePath + TENDER_STRUCT);
+		if (document == null) {
+			throw new RuntimeException();
+		}
+		List<?> elements = document.getRootElement().elements("chapter");
+		if (elements == null) {
+			return Optional.empty();
+		}
+		return Recursions.stream(ElementUtils.toStreamFun("chapterList", "chapter")).toStream(elements.stream().map(t -> (Element) t))
+				.findAny(t -> t.elementText("relChapterType").equals(relChapterType)).map(ElementUtils.toStreamFun("tableList", "tableInfo"))
+				.map(s -> {
+					return s.map(ParsingStructXmlUtils::initTemplateTable).peek(t -> {
+						t.setTenderId(tenderId);
+						t.setSupplierId(Constants.BIDDING_ID);
+						t.setRelChapterType(relChapterType);
+						Optional.of(t).map(TemplateTable::getXmlPath).map(biddingFilePath::concat).map(ParsingXmlUtils::parsingTableXML).map(JsonUtil::jsonObjectToStr).ifPresent(t::setTableInfo);
+					}).collect(Collectors.toList());
+				});
+	}
+	
+	/**
+	 * @Description: 初始化小范本表格
+	 * @author chenxw
+	 * @param templateTableElement
+	 * @return
+	 */
+	private static TemplateTable initTemplateTable(Element templateTableElement) {
+		TemplateTable templateTable = new TemplateTable();
+		String tableId = templateTableElement.elementTextTrim("tableId");
+		templateTable.setId(StringUtils.isEmpty(tableId) ? UuidUtils.getUUID() : tableId);
+		templateTable.setDataCode(templateTableElement.elementTextTrim("bookMarkName"));
+		templateTable.setXmlPath(templateTableElement.elementTextTrim("xmlPath"));
+		templateTable.setTableName(templateTableElement.elementTextTrim("tableName"));
+		return templateTable;
+	}
+	
+	/**
+	 * @Description: 解析小范本表单数据
+	 * @author chenxw
+	 * @param tenderId
+	 * @param supplierId
+	 * @param relChapterType
+	 * @param fileItemElementList
+	 * @return
+	 */
+	public static Optional<List<TemplateDataItem>> resolverObeTemplateDataItem(String tenderId, String supplierId, String relChapterType, List<Element> fileItemElementList, String bidFilePath) {
+		if (StringUtils.isEmpty(tenderId) || StringUtils.isEmpty(supplierId) || StringUtils.isEmpty(relChapterType) || CollectionUtils.isNull(fileItemElementList)) {
+			return Optional.empty();
+		}
+		return fileItemElementList.stream().filter(t -> {
+			return relChapterType.equals(t.elementTextTrim("chapterType"));
+		}).findAny().map(t -> {
+			return t.elementTextTrim("fileId");
+		}).map(t -> {
+			return t.concat(Constants.XML);
+		}).map(t -> {
+			return bidFilePath.concat(t);
+		}).map(XmlUtils::getXmlDocument).map(Document::getRootElement).map(t -> t.elements("dataItem")).map(l -> {
+			return streamElement(l).map(ParsingStructXmlUtils::initTemplateDataItem).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setSupplierId(supplierId);
+				t.setRelChapterType(relChapterType);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化小范本表格
+	 * @author chenxw
+	 * @param templateTableElement
+	 * @return
+	 */
+	private static TemplateDataItem initTemplateDataItem(Element templateDataItemElement) {
+		TemplateDataItem templateDataItem = new TemplateDataItem();
+		templateDataItem.setId(UuidUtils.getUUID());
+		templateDataItem.setDataCode(templateDataItemElement.elementTextTrim("id"));
+		templateDataItem.setName(templateDataItemElement.elementTextTrim("name"));
+		templateDataItem.setValue(templateDataItemElement.elementTextTrim("value"));
+		templateDataItem.setType(templateDataItemElement.elementTextTrim("type"));
+		templateDataItem.setDataType(templateDataItemElement.elementTextTrim("dataType"));
+		templateDataItem.setUnit(templateDataItemElement.elementTextTrim("unit"));
+		return templateDataItem;
+	}
+	
+	/**
+	 * @Description: 解析营业执照
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @param xmlFilePath
+	 * @param consumer
+	 * @return
+	 */
+	public static Optional<List<BusinessLicense>> resolverBusinessLicense(String tenderId, String modelDataId, String xmlFilePath, Consumer<AttachmentFileOperation> consumer) {
+		return Optional.ofNullable(XmlUtils.getXmlDocument(xmlFilePath)).map(t -> t.getRootElement().elements("BusinessLicense")).map(l -> {
+			return streamElement(l).map(t -> {
+				BusinessLicense businessLicense = initBusinessLicense(t);
+				consumer.accept(new AttachmentFileOperation(tenderId, businessLicense.getId(), t.element("scanCertificate")));
+				return businessLicense;
+			}).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setModelDataId(modelDataId);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化营业执照
+	 * @author chenxw
+	 * @param businessLicenseElement
+	 * @return
+	 */
+	private static BusinessLicense initBusinessLicense(Element businessLicenseElement) {
+		BusinessLicense businessLicense = new BusinessLicense();
+		businessLicense.setId(UuidUtils.getUUID());
+		businessLicense.setRegisterNumber(businessLicenseElement.elementTextTrim("registerNumber"));
+		businessLicense.setCompanyName(businessLicenseElement.elementTextTrim("companyName"));
+		businessLicense.setCompanyType(businessLicenseElement.elementTextTrim("companyType"));
+		businessLicense.setCompanyAddress(businessLicenseElement.elementTextTrim("companyAddress"));
+		businessLicense.setLegalRepresentative(businessLicenseElement.elementTextTrim("legalRepresentative"));
+		businessLicense.setRegisterCapital(businessLicenseElement.elementTextTrim("registerCapital"));
+		businessLicense.setEstablishDate(businessLicenseElement.elementTextTrim("establishDate"));
+		businessLicense.setBusnissTermStartDate(businessLicenseElement.elementTextTrim("busnissTermStartDate"));
+		businessLicense.setBusnissTermEndtDate(businessLicenseElement.elementTextTrim("busnissTermEndDate"));
+		businessLicense.setBusinessScope(businessLicenseElement.elementTextTrim("businessScope"));
+		businessLicense.setRegisterInstitution(businessLicenseElement.elementTextTrim("registerInstitution"));
+		businessLicense.setIsPerpetual(businessLicenseElement.elementTextTrim("isPerpetual"));
+		businessLicense.setIsInAreaEnterprises(businessLicenseElement.elementTextTrim("isInAreaEnterprises"));
+		return businessLicense;
+	}
+	
+	/**
+	 * @Description: 解析财务报表
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @param xmlFilePath
+	 * @param consumer
+	 * @return
+	 */
+	public static Optional<List<Finance>> resolverFinance(String tenderId, String modelDataId, String xmlFilePath, Consumer<AttachmentFileOperation> consumer) {
+		return Optional.ofNullable(XmlUtils.getXmlDocument(xmlFilePath)).map(t -> t.getRootElement().elements("Finance")).map(l -> {
+			return streamElement(l).map(t -> {
+				Finance finance = initFinance(t);
+				consumer.accept(new AttachmentFileOperation(tenderId, finance.getId(), t.element("scanFinance")));
+				return finance;
+			}).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setModelDataId(modelDataId);
+//				t.getBalanceSheet().setTenderId(tenderId);
+//				t.getBalanceSheet().setFinanceId(t.getId());
+//				t.getProfitlossSheet().setTenderId(tenderId);
+//				t.getProfitlossSheet().setFinanceId(t.getId());
+//				t.getCashSheet().setTenderId(tenderId);
+//				t.getCashSheet().setFinanceId(t.getId());
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化财务报表
+	 * @author chenxw
+	 * @param financeElement
+	 * @return
+	 */
+	private static Finance initFinance(Element financeElement) {
+		Finance finance = new Finance();
+		finance.setId(UuidUtils.getUUID());
+		finance.setAnnual(financeElement.elementTextTrim("annual"));
+//		finance.setRegisteredCapital(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("registeredCapital")));
+		finance.setTotal(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("total")));
+		finance.setProfitLossProfit(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("profitLossprofit")));
+		finance.setOperatingIncome(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("operatingIncome")));
+		finance.setLiabilitiesRate(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("liabilitiesRate")));
+		finance.setCurrentAssets(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("currentAssets")));
+		finance.setCurrentLiabilities(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("currentLiabilities")));
+		finance.setCurrentRate(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("currentRate")));
+		finance.setProfitRatio(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("profitRatio")));
+		finance.setOperatingMargin(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("operatingMargin")));
+		finance.setRetainedProfits(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("retainedProfits")));
+		finance.setCompanyName(financeElement.elementTextTrim("companyName"));
+		finance.setNetWorth(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("netWorth")));
+//		finance.setFixedAssets(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("fixedAssets")));
+//		finance.setNetCashFlow(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("netCashFlow")));
+//		finance.setReturnOnEquity(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("returnOnEquity")));
+//		finance.setReturnOnTotalAsset(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("returnOnTotalAsset")));
+		finance.setQuickRatio(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("quickRatio")));
+		finance.setTotalliabilities(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("totalliabilities")));
+		finance.setTotalcost(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("totalcost")));
+		finance.setQuickassets(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("quickassets")));
+		finance.setMainIncomeProfits(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("mainIncomeProfits")));
+		finance.setPrimeOperatingRevenue(ObjectUtils.getObjBigDecimal(financeElement.elementTextTrim("primeOperatingRevenue")));
+//		finance.setBalanceSheet(initBalanceSheet(financeElement.element("BalanceSheet")));
+//		finance.setProfitlossSheet(initProfitlossSheet(financeElement.element("ProfitLossSheet")));
+//		finance.setCashSheet(initCashSheet(financeElement.element("CashSheet")));
+		return finance;
+	}
+	
+	/**
+	 * @Description: 初始化资产负债表
+	 * @author chenxw
+	 * @param balanceSheetElement
+	 * @return
+	 */
+//	private static BalanceSheet initBalanceSheet(Element balanceSheetElement) {
+//		BalanceSheet balanceSheet = new BalanceSheet();
+//		balanceSheet.setId(UuidUtils.getUUID());
+//		balanceSheet.setBalanceTotal(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("balanceTotal")));
+//		balanceSheet.setBalanceCecurrentAssets(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("balanceCecurrentAssets")));
+//		balanceSheet.setInventory(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("inventory")));
+//		balanceSheet.setReceivables(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("receivables")));
+//		balanceSheet.setBadAssets(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("badAssets")));
+//		balanceSheet.setBalanceTotalliabilities(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("balanceTotalliabilities")));
+//		balanceSheet.setBalanceCurrentLiabilities(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("balanceCurrentLiabilities")));
+//		balanceSheet.setOwnershipInterest(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("ownershipInterest")));
+//		balanceSheet.setAbnormalIncrease(ObjectUtils.getObjBigDecimal(balanceSheetElement.elementTextTrim("abnormalIncrease")));
+//		return balanceSheet;
+//	}
+	
+	/**
+	 * @Description: 初始化损益表
+	 * @author chenxw
+	 * @param profitlossSheetElement
+	 * @return
+	 */
+//	private static ProfitlossSheet initProfitlossSheet(Element profitlossSheetElement) {
+//		ProfitlossSheet profitlossSheet = new ProfitlossSheet();
+//		profitlossSheet.setId(UuidUtils.getUUID());
+//		profitlossSheet.setMainIncome(ObjectUtils.getObjBigDecimal(profitlossSheetElement.elementTextTrim("mainIncome")));
+//		profitlossSheet.setMainCost(ObjectUtils.getObjBigDecimal(profitlossSheetElement.elementTextTrim("mainCost")));
+//		profitlossSheet.setFinancialCost(ObjectUtils.getObjBigDecimal(profitlossSheetElement.elementTextTrim("financialCost")));
+//		profitlossSheet.setOtherCosts(ObjectUtils.getObjBigDecimal(profitlossSheetElement.elementTextTrim("otherCosts")));
+//		profitlossSheet.setDevelopmentAndTransferCosts(ObjectUtils.getObjBigDecimal(profitlossSheetElement.elementTextTrim("developmentAndTransferCosts")));
+//		profitlossSheet.setProfitLossprofit(ObjectUtils.getObjBigDecimal(profitlossSheetElement.elementTextTrim("profitLossprofit")));
+//		profitlossSheet.setProfitRetainedProfits(ObjectUtils.getObjBigDecimal(profitlossSheetElement.elementTextTrim("profitRetainedProfits")));
+//		return profitlossSheet;
+//	}
+	
+	/**
+	 * @Description: 初始化现金流量表
+	 * @author chenxw
+	 * @param cashSheetElement
+	 * @return
+	 */
+//	private static CashSheet initCashSheet(Element cashSheetElement) {
+//		CashSheet cashSheet = new CashSheet();
+//		cashSheet.setId(UuidUtils.getUUID());
+//		cashSheet.setOperatingNetCashFlow(ObjectUtils.getObjBigDecimal(cashSheetElement.elementTextTrim("operatingNetCashFlow")));
+//		return cashSheet;
+//	}
+	
+	/**
+	 * @Description: 解析业绩
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @param xmlFilePath
+	 * @param consumer
+	 * @param mark 
+	 * @return
+	 */
+	public static Optional<List<Performance>> resolverPerformance(String tenderId, String modelDataId, String xmlFilePath, Consumer<AttachmentFileOperation> consumer, String mark) {
+		return Optional.ofNullable(XmlUtils.getXmlDocument(xmlFilePath)).map(t -> t.getRootElement().elements("Performance")).map(l -> {
+			return streamElement(l).filter(t -> {
+				return mark.equals(t.elementTextTrim("status"));
+			}).map(t -> {
+				Performance performance = initPerformance(t);
+				consumer.accept(new AttachmentFileOperation(tenderId, performance.getId(), t.element("scanSingning")));
+				return performance;
+			}).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setModelDataId(modelDataId);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化业绩
+	 * @author chenxw
+	 * @param performanceElement
+	 * @return
+	 */
+	private static Performance initPerformance(Element performanceElement) {
+		Performance performance = new Performance();
+		performance.setId(UuidUtils.getUUID());
+		performance.setPurchasingUnit(performanceElement.elementTextTrim("purchasingUnit"));
+		performance.setPartner(performanceElement.elementTextTrim("partner"));
+		performance.setProjectName(performanceElement.elementTextTrim("projectName"));
+		performance.setSingningDate(performanceElement.elementTextTrim("singningDate"));
+		performance.setEndTime(performanceElement.elementTextTrim("endTime"));
+		performance.setSingningTotal(performanceElement.elementTextTrim("singningTotal"));
+		performance.setPurchaser(performanceElement.elementTextTrim("purchaser"));
+		performance.setPurchaserPhone(performanceElement.elementTextTrim("purchaserPhone"));
+		performance.setStatus(performanceElement.elementTextTrim("status"));
+		performance.setSupplierName(performanceElement.elementTextTrim("supplierName"));
+		performance.setProjectAddress(performanceElement.elementTextTrim("projectAddress"));
+		performance.setBuyerName(performanceElement.elementTextTrim("buyerName"));
+		performance.setBuyerAddress(performanceElement.elementTextTrim("buyerAddress"));
+		performance.setBuyerPhoneNumber(performanceElement.elementTextTrim("buyerPhoneNumber"));
+		performance.setStartTime(performanceElement.elementTextTrim("startTime"));
+		performance.setWorkUndertaken(performanceElement.elementTextTrim("workUndertaken"));
+		performance.setProjectQuantity(performanceElement.elementTextTrim("projectQuantity"));
+		performance.setProjectManager(performanceElement.elementTextTrim("projectManager"));
+		performance.setTechnicalDirector(performanceElement.elementTextTrim("technicalDirector"));
+		performance.setChiefSupervisionEngineer(performanceElement.elementTextTrim("chiefSupervisionEngineer"));
+		performance.setCsePhoneNumber(performanceElement.elementTextTrim("CSEPhoneNumber"));
+		performance.setProjectDesc(performanceElement.elementTextTrim("projectDesc"));
+		performance.setProjectRangeAndContent(performanceElement.elementTextTrim("projectRangeAndContent"));
+		performance.setSupplierWorkerCountmax(performanceElement.elementTextTrim("supplierWorkerCountMax"));
+		performance.setSupplierWorkerCountave(performanceElement.elementTextTrim("supplierWorkerCountAve"));
+		performance.setProjectDeviceResult(performanceElement.elementTextTrim("projectDeviceResult"));
+		performance.setBuyerLinkman(performanceElement.elementTextTrim("buyerLinkman"));
+		performance.setIsHavrAccessory(performanceElement.elementTextTrim("isHavrAccessory"));
+		performance.setIsOurCompanyProject(performanceElement.elementTextTrim("isOurCompanyProject"));
+		performance.setServiceScope(performanceElement.elementTextTrim("serviceScope"));
+		performance.setDeviceName(performanceElement.elementTextTrim("deviceName"));
+		performance.setDevicetypeSpecification(performanceElement.elementTextTrim("devicetypeSpecification"));
+		performance.setTotalCapacity(performanceElement.elementTextTrim("totalCapacity"));
+		performance.setNumber(performanceElement.elementTextTrim("number"));
+		performance.setContractTime(performanceElement.elementTextTrim("contractTime"));
+		performance.setCommissioningTime(performanceElement.elementTextTrim("commissioningTime"));
+		performance.setMemo(performanceElement.elementTextTrim("memo"));
+		performance.setProjectScale(performanceElement.elementTextTrim("projectScale"));
+		performance.setProfessionalNumber(performanceElement.elementTextTrim("professionalNumber"));
+		performance.setProfessionalWorkload(performanceElement.elementTextTrim("professionalWorkload"));
+		performance.setPartnerProfessionalWorkload(performanceElement.elementTextTrim("partnerProfessionalWorkload"));
+		performance.setSupervisionCcontent(performanceElement.elementTextTrim("supervisionCcontent"));
+		performance.setSupervisionResult(performanceElement.elementTextTrim("supervisionResult"));
+		performance.setKeyStaffProfessionalAndDuty(performanceElement.elementTextTrim("keyStaffProfessionalAndDuty"));
+		performance.setServiceDesc(performanceElement.elementTextTrim("serviceDesc"));
+		performance.setExecutionDate(performanceElement.elementTextTrim("serviceDesc"));
+		performance.setProjectScaleAndType(performanceElement.elementTextTrim("projectScaleAndType"));
+		performance.setDesignStage(performanceElement.elementTextTrim("designStage"));
+		performance.setDesignRange(performanceElement.elementTextTrim("designRange"));
+		performance.setCooperationWay(performanceElement.elementTextTrim("cooperationWay"));
+		performance.setContractExecuteCondition(performanceElement.elementTextTrim("contractExecuteCondition"));
+		return performance;
+	}
+	
+	/**
+	 * @Description: 解析投标人基本情况
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @param xmlFilePath
+	 * @return
+	 */
+	public static Optional<List<BidderBasicInfo>> resolverBidderBasicInfo(String tenderId, String modelDataId, String xmlFilePath, Consumer<AttachmentFileOperation> consumer) {
+		return Optional.ofNullable(XmlUtils.getXmlDocument(xmlFilePath)).map(t -> t.getRootElement().elements("bidderBasicInfo")).map(l -> {
+			return streamElement(l).map(t -> {
+				BidderBasicInfo bidderBasicInfo = initBidderBasicInfo(t);
+				consumer.accept(new AttachmentFileOperation(tenderId, bidderBasicInfo.getId(), t.element("scanCertificate")));
+				return bidderBasicInfo;
+			}).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setModelDataId(modelDataId);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化投标人基本情况
+	 * @author chenxw
+	 * @param bidderBasicInfoElement
+	 * @return
+	 */
+	private static BidderBasicInfo initBidderBasicInfo(Element bidderBasicInfoElement) {
+		BidderBasicInfo bidderBasicInfo = new BidderBasicInfo();
+		bidderBasicInfo.setId(UuidUtils.getUUID());
+		bidderBasicInfo.setCompanyName(bidderBasicInfoElement.elementTextTrim("companyName"));
+		bidderBasicInfo.setRegisterLocation(bidderBasicInfoElement.elementTextTrim("registerLocation"));
+		bidderBasicInfo.setPostalCode(bidderBasicInfoElement.elementTextTrim("postalCode"));
+		bidderBasicInfo.setLinkMan(bidderBasicInfoElement.elementTextTrim("linkMan"));
+		bidderBasicInfo.setLinkManPhone(bidderBasicInfoElement.elementTextTrim("linkManPhone"));
+		bidderBasicInfo.setLinkManFax(bidderBasicInfoElement.elementTextTrim("linkManFax"));
+		bidderBasicInfo.setLinkManWebsite(bidderBasicInfoElement.elementTextTrim("linkManWebSite"));
+		bidderBasicInfo.setOrgStructure(bidderBasicInfoElement.elementTextTrim("orgStructure"));
+		bidderBasicInfo.setLegalRepresentativeName(bidderBasicInfoElement.elementTextTrim("legalRepresentativeName"));
+		bidderBasicInfo.setLegalRepresentativeTitle(bidderBasicInfoElement.elementTextTrim("legalRepresentativeTitle"));
+		bidderBasicInfo.setLegalRepresentativePhone(bidderBasicInfoElement.elementTextTrim("legalRepresentativePhone"));
+		bidderBasicInfo.setTechnicalDirectorName(bidderBasicInfoElement.elementTextTrim("technicalDirectorName"));
+		bidderBasicInfo.setTechnicalDirectorTitle(bidderBasicInfoElement.elementTextTrim("technicalDirectorTitle"));
+		bidderBasicInfo.setTechnicalDirectorPhone(bidderBasicInfoElement.elementTextTrim("technicalDirectorPhone"));
+		bidderBasicInfo.setSetupTime(bidderBasicInfoElement.elementTextTrim("setupTime"));
+		bidderBasicInfo.setCompanyQualificationLevel(bidderBasicInfoElement.elementTextTrim("companyQualificationLevel"));
+		bidderBasicInfo.setRegisteredCapital(bidderBasicInfoElement.elementTextTrim("registeredCapital"));
+		bidderBasicInfo.setDepositBank(bidderBasicInfoElement.elementTextTrim("depositBank"));
+		bidderBasicInfo.setBussinessLicense(bidderBasicInfoElement.elementTextTrim("bussinessLicense"));
+		bidderBasicInfo.setBankAccount(bidderBasicInfoElement.elementTextTrim("bankAccount"));
+		bidderBasicInfo.setEmployeeNumber(bidderBasicInfoElement.elementTextTrim("employeeNumber"));
+		bidderBasicInfo.setPurchaserNumber(bidderBasicInfoElement.elementTextTrim("purchaserNumber"));
+		bidderBasicInfo.setSeniorProfessionalPostNumber(bidderBasicInfoElement.elementTextTrim("seniorProfessionalPostNumber"));
+		bidderBasicInfo.setMediumProfessionalPostNumber(bidderBasicInfoElement.elementTextTrim("mediumProfessionalPostNumber"));
+		bidderBasicInfo.setPrimaryProfessionalPostNumber(bidderBasicInfoElement.elementTextTrim("primaryProfessionalPostNumber"));
+		bidderBasicInfo.setArtisanNumber(bidderBasicInfoElement.elementTextTrim("artisanNumber"));
+		bidderBasicInfo.setBusinessScope(bidderBasicInfoElement.elementTextTrim("businessScope"));
+		bidderBasicInfo.setEnterpriseNature(bidderBasicInfoElement.elementTextTrim("enterpriseNature"));
+		bidderBasicInfo.setEquityStructure(bidderBasicInfoElement.elementTextTrim("equityStructure"));
+		bidderBasicInfo.setRelatedCompanyInfo(bidderBasicInfoElement.elementTextTrim("relatedCompanyInfo"));
+		bidderBasicInfo.setServiceAbility(bidderBasicInfoElement.elementTextTrim("serviceAbility"));
+		bidderBasicInfo.setPreInputDevice(bidderBasicInfoElement.elementTextTrim("preInputDevice"));
+		bidderBasicInfo.setMemo(bidderBasicInfoElement.elementTextTrim("memo"));
+		return bidderBasicInfo;
+	}
+	
+	/**
+	 * @Description: 解析认证证书
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @param xmlFilePath
+	 * @param consumer
+	 * @return
+	 */
+	public static Optional<List<Qualification>> resolverQualification(String tenderId, String modelDataId, String xmlFilePath, Consumer<AttachmentFileOperation> consumer) {
+		return Optional.ofNullable(XmlUtils.getXmlDocument(xmlFilePath)).map(t -> t.getRootElement().elements("Qualification")).map(l -> {
+			return streamElement(l).map(t -> {
+				Qualification qualification = initQualification(t);
+				consumer.accept(new AttachmentFileOperation(tenderId, qualification.getId(), t.element("scanCertificate")));
+				return qualification;
+			}).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setModelDataId(modelDataId);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化认证证书
+	 * @author chenxw
+	 * @param qualificationElement
+	 * @return
+	 */
+	private static Qualification initQualification(Element qualificationElement) {
+		Qualification qualification = new Qualification();
+		qualification.setId(UuidUtils.getUUID());
+		qualification.setCertificateName(qualificationElement.elementTextTrim("certificateName"));
+		qualification.setAwardProjectName(qualificationElement.elementTextTrim("awardProjectName"));
+		qualification.setCompanyName(qualificationElement.elementTextTrim("companyName"));
+		qualification.setAwardLevel(qualificationElement.elementTextTrim("awardLevel"));
+		qualification.setCertificateNumber(qualificationElement.elementTextTrim("certificateNumber"));
+		qualification.setIssueAuthority(qualificationElement.elementTextTrim("issueAuthority"));
+		qualification.setIssueDate(qualificationElement.elementTextTrim("issueDate"));
+		qualification.setPeriodValidity(qualificationElement.elementTextTrim("periodValidity"));
+		qualification.setProjectName(qualificationElement.elementTextTrim("projectName"));
+		return qualification;
+	}
+	
+	/**
+	 * @Description: 解析项目负责人
+	 * @author chenxw
+	 * @param tenderId
+	 * @param modelDataId
+	 * @param xmlFilePath
+	 * @param consumer
+	 * @return
+	 */
+	public static Optional<List<ProjectLeader>> resolverProjectLeader(String tenderId, String modelDataId, String xmlFilePath, Consumer<AttachmentFileOperation> consumer) {
+		return Optional.ofNullable(XmlUtils.getXmlDocument(xmlFilePath)).map(t -> t.getRootElement().elements("projectLeader")).map(l -> {
+			return streamElement(l).map(t -> {
+				ProjectLeader projectLeader = initProjectLeader(t);
+				consumer.accept(new AttachmentFileOperation(tenderId, projectLeader.getId(), t.element("scanSingningList")));
+				projectLeader.setCertificateList(resolverCertificate(tenderId, projectLeader.getId(), t.element("certificateList"), consumer));
+				projectLeader.setWorkExperienceList(resolverWorkExperience(t.element("workExperienceList"), tenderId, projectLeader.getId()));
+				return projectLeader;
+			}).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setModelDataId(modelDataId);
+			}).collect(Collectors.toList());
+		});
+	}
+	
+	/**
+	 * @Description: 初始化项目负责人
+	 * @author chenxw
+	 * @param qualificationElement
+	 * @return
+	 */
+	private static ProjectLeader initProjectLeader(Element projectLeaderElement) {
+		ProjectLeader projectLeader = new ProjectLeader();
+		projectLeader.setId(UuidUtils.getUUID());
+		projectLeader.setCompanyName(projectLeaderElement.elementTextTrim("companyName"));
+		projectLeader.setLeaderName(projectLeaderElement.elementTextTrim("leaderName"));
+		projectLeader.setIdnumber(projectLeaderElement.elementTextTrim("idnumber"));
+		projectLeader.setAge(projectLeaderElement.elementTextTrim("age"));
+		projectLeader.setJobTitle(projectLeaderElement.elementTextTrim("jobTitle"));
+		projectLeader.setWorkExperience(projectLeaderElement.elementTextTrim("workExperience"));
+		projectLeader.setCurrentMajorExperience(projectLeaderElement.elementTextTrim("currentMajorExperience"));
+		projectLeader.setGraduateSchool(projectLeaderElement.elementTextTrim("graduateSchool"));
+		projectLeader.setGraduateMajor(projectLeaderElement.elementTextTrim("graduateMajor"));
+		projectLeader.setEducation(projectLeaderElement.elementTextTrim("education"));
+		projectLeader.setProfessionalTitle(projectLeaderElement.elementTextTrim("professionalTitle"));
+		projectLeader.setIsLeaderFlag(projectLeaderElement.elementTextTrim("isLeaderFlag"));
+		return projectLeader;
+	}
+	
+	/**
+	 * @Description: 解析证书信息
+	 * @author chenxw
+	 * @param tenderId
+	 * @param projectLeaderId
+	 * @param certificateListElement
+	 * @param consumer
+	 * @return
+	 */
+	private static List<Certificate> resolverCertificate(String tenderId, String projectLeaderId, Element certificateListElement, Consumer<AttachmentFileOperation> consumer) {
+		return Optional.ofNullable(certificateListElement).map(t -> t.elements("projectLeaderCertificate")).map(l -> {
+			return streamElement(l).map(t -> {
+				Certificate certificate = initCertificate(t);
+				consumer.accept(new AttachmentFileOperation(tenderId, certificate.getId(), t.element("scanCertificate"), true));
+				return certificate;
+			}).peek(t -> {
+				t.setTenderId(tenderId);
+				t.setProjectLeaderId(projectLeaderId);
+			}).collect(Collectors.toList());
+		}).orElse(null);
+	}
+	
+	/**
+	 * @Description: 初始化证书信息
+	 * @author chenxw
+	 * @param projectLeaderCertificateElement
+	 * @return
+	 */
+	private static Certificate initCertificate(Element projectLeaderCertificateElement) {
+		Certificate certificate = new Certificate();
+		certificate.setId(UuidUtils.getUUID());
+		certificate.setCertificateNo(projectLeaderCertificateElement.elementTextTrim("certificateNo"));
+		certificate.setCertificateName(projectLeaderCertificateElement.elementTextTrim("certificateName"));
+		certificate.setCertificateLevel(projectLeaderCertificateElement.elementTextTrim("certificateLevel"));
+		certificate.setSortNo(Optional.ofNullable(projectLeaderCertificateElement.elementTextTrim("SortNo")).map(Integer::valueOf).orElse(Integer.MAX_VALUE));
+		return certificate;
+	}
+	
+	/**
+	 * @Description: 解析工作经历列表
+	 * @author chenxw
+	 * @param workExperienceListElement
+	 * @param tenderId
+	 * @param projectLeaderId
+	 * @return 
+	 */
+	private static List<WorkExperience> resolverWorkExperience(
+			Element workExperienceListElement, 
+			String tenderId, 
+			String projectLeaderId) {
+		return Optional.ofNullable(workExperienceListElement)
+				.map(Element::elements)
+				.map(l -> IntStream.range(0, l.size())
+						.mapToObj(i -> initWorkExperience((Element) l.get(i), i))
+						.peek(t -> {
+							t.setTenderId(tenderId);
+							t.setProjectLeaderId(projectLeaderId);
+						})
+						.collect(Collectors.toList()))
+				.orElse(null);
+	}
+	
+	/**
+	 * @Description: 初始化工作经历
+	 * @author chenxw
+	 * @param workExperienceElement
+	 * @param
+	 * @return
+	 */
+	private static WorkExperience initWorkExperience(Element workExperienceElement, int sortNo) {
+		return Optional.of(workExperienceElement).map(e -> {
+			WorkExperience workExperience = new WorkExperience();
+			workExperience.setId(UuidUtils.getUUID());
+			workExperience.setTime(e.elementTextTrim("time"));
+			workExperience.setProjectName(e.elementTextTrim("projectName"));
+			workExperience.setJobTitle(e.elementTextTrim("jobTitle"));
+			workExperience.setContractInfo(e.elementTextTrim("contractInfo"));
+			workExperience.setCapacity(e.elementTextTrim("capacity"));
+			workExperience.setBearWork(e.elementTextTrim("bearWork"));
+			workExperience.setSortNo(sortNo);
+			return workExperience;
+		}).get();
+	}
+	
+	/**
+	 * @Description: 解析附件信息
+	 * @author chenxw
+	 * @param attachmentFileOperation
+	 * @return
+	 */
+	public static Optional<List<AttachmentFile>> resolverAttachmentFile(AttachmentFileOperation attachmentFileOperation) {
+		Optional<AttachmentFileOperation> attachmentFileOperationOptional = Optional.ofNullable(attachmentFileOperation);
+		Consumer<AttachmentFile> action = a -> {
+			attachmentFileOperationOptional.map(t -> t.tenderId).ifPresent(t -> a.setTenderId(t));
+			attachmentFileOperationOptional.map(t -> t.businessId).ifPresent(t -> a.setBusinessId(t));
+		};
+		if (attachmentFileOperation.single) return attachmentFileOperationOptional.map(t -> t.element)
+				.map(e -> Stream.of(e).map(ParsingStructXmlUtils::initAttachmentFile).peek(action).collect(Collectors.toList()));
+		return attachmentFileOperationOptional.map(t -> t.element).map(t -> t.elements("attachmentFileWithSign"))
+				.map(l -> streamElement(l).map(ParsingStructXmlUtils::initAttachmentFile).peek(action).collect(Collectors.toList()));
+	}
+	
+	/**
+	 * @Description: 初始化附件信息
+	 * @author chenxw
+	 * @param attachmentFileWithSignElement
+	 * @return
+	 */
+	private static AttachmentFile initAttachmentFile(Element attachmentFileWithSignElement) {
+		AttachmentFile attachmentFile = new AttachmentFile();
+		attachmentFile.setId(UuidUtils.getUUID());
+		attachmentFile.setCreateTime(BusinessNowTimeUtils.getNowDate());
+		attachmentFile.setFileUrl(attachmentFileWithSignElement.elementTextTrim("DownloadUrl"));
+		attachmentFile.setFileName(attachmentFileWithSignElement.elementTextTrim("FileName"));
+		return attachmentFile;
+	}
+	
+	/**
+	 * @Description: 附件信息操作类
+	 * @author chenxw
+	 */
+	public static class AttachmentFileOperation {
+		
+		private final String tenderId;
+		private final String businessId;
+		private final Element element;
+		private final boolean single;
+		
+		/** 
+		 * @author chenxw
+		 * @param tenderId
+		 * @param businessId
+		 * @param element 
+		 */
+		public AttachmentFileOperation(String tenderId, String businessId, Element element) {
+			this(tenderId, businessId, element, false);
+		}
+		
+		/** 
+		 * @author chenxw
+		 * @param tenderId
+		 * @param businessId
+		 * @param element
+		 * @param single 
+		 */
+		public AttachmentFileOperation(String tenderId, String businessId, Element element, boolean single) {
+			this.tenderId = tenderId;
+			this.businessId = businessId;
+			this.element = element;
+			this.single = single;
+		}
+		
+	}
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/value_list/CreditGrade.java b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/CreditGrade.java
new file mode 100644
index 0000000000000000000000000000000000000000..1eca7130ca443839adc3b25c015c0909fc7ebfe4
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/CreditGrade.java
@@ -0,0 +1,43 @@
+package com.gx.obe.struct.value_list;
+
+import java.math.BigDecimal;
+
+/** 
+ * @Description: EQ_Qualification_ZXDJ
+ * @author wangxiang 
+ */
+public class CreditGrade {
+	
+	private String orgName;
+	
+	private String issueOrgName;
+	
+	private String grade;
+
+	public String getOrgName() {
+		return orgName;
+	}
+
+	public void setOrgName(String orgName) {
+		this.orgName = orgName;
+	}
+
+	public String getIssueOrgName() {
+		return issueOrgName;
+	}
+
+	public void setIssueOrgName(String issueOrgName) {
+		this.issueOrgName = issueOrgName;
+	}
+
+	public String getGrade() {
+		return grade;
+	}
+
+	public void setGrade(String grade) {
+		this.grade = grade;
+	}
+
+	
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Finance.java b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Finance.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae8b7f0100cf34dffd8af76a1093a05c961201b9
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Finance.java
@@ -0,0 +1,42 @@
+package com.gx.obe.struct.value_list;
+
+import java.math.BigDecimal;
+
+/** 
+ * @Description: EQ_ProfitRatio
+ * @author wangxiang 
+ */
+public class Finance {
+	
+	private String orgName;
+	
+	private int annual;
+	
+	private BigDecimal value;
+
+	public String getOrgName() {
+		return orgName;
+	}
+
+	public void setOrgName(String orgName) {
+		this.orgName = orgName;
+	}
+
+	public int getAnnual() {
+		return annual;
+	}
+
+	public void setAnnual(int annual) {
+		this.annual = annual;
+	}
+
+	public BigDecimal getValue() {
+		return value;
+	}
+
+	public void setValue(BigDecimal value) {
+		this.value = value;
+	}
+	
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Goods.java b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Goods.java
new file mode 100644
index 0000000000000000000000000000000000000000..0adb2d3e4c28c00322c8acd1d0ddbf1d5a69405d
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Goods.java
@@ -0,0 +1,41 @@
+package com.gx.obe.struct.value_list;
+
+/** 
+ * @Description: EQ_ProfitRatio
+ * @author wangxiang 
+ */
+public class Goods {
+	
+	private String goodsName;
+	
+	private String goodsUnit;
+	
+	private int goodsQuantity;
+
+	public String getGoodsName() {
+		return goodsName;
+	}
+
+	public void setGoodsName(String goodsName) {
+		this.goodsName = goodsName;
+	}
+
+	public String getGoodsUnit() {
+		return goodsUnit;
+	}
+
+	public void setGoodsUnit(String goodsUnit) {
+		this.goodsUnit = goodsUnit;
+	}
+
+	public int getGoodsQuantity() {
+		return goodsQuantity;
+	}
+
+	public void setGoodsQuantity(int goodsQuantity) {
+		this.goodsQuantity = goodsQuantity;
+	}
+	
+	
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/value_list/ParamValue.java b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/ParamValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..51c2b233d95293770e7e4609077152d7d25138dc
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/ParamValue.java
@@ -0,0 +1,31 @@
+package com.gx.obe.struct.value_list;
+
+/** 
+ * @Description: 
+ * @author wangxiang 
+ */
+public class ParamValue {
+	
+	private String dataType;
+	
+	private String dataValue;
+
+	public String getDataType() {
+		return dataType;
+	}
+
+	public void setDataType(String dataType) {
+		this.dataType = dataType;
+	}
+
+	public String getDataValue() {
+		return dataValue;
+	}
+
+	public void setDataValue(String dataValue) {
+		this.dataValue = dataValue;
+	}
+	
+
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/value_list/ParamValues.java b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/ParamValues.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8eb17ce1c9c87a5b8a48ad02b61fc6adeccf1c5
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/ParamValues.java
@@ -0,0 +1,23 @@
+package com.gx.obe.struct.value_list;
+
+import java.util.List;
+
+/** 
+ * @Description: 
+ * @author wangxiang 
+ */
+public class ParamValues {
+	
+	private List<ParamValue> paramValueList;
+
+	public List<ParamValue> getParamValueList() {
+		return paramValueList;
+	}
+
+	public void setParamValueList(List<ParamValue> paramValueList) {
+		this.paramValueList = paramValueList;
+	}
+	
+
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Performance.java b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Performance.java
new file mode 100644
index 0000000000000000000000000000000000000000..8fe567250f921656b853edceeb56f9cbb9779c33
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/Performance.java
@@ -0,0 +1,43 @@
+package com.gx.obe.struct.value_list;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/** 
+ * @Description: EQ_Achievements
+ * @author wangxiang 
+ */
+public class Performance {
+	
+	private String orgName;
+	
+	private int performanceCount;
+	
+	private List<SimilarProduct> similarProductList;
+
+	public String getOrgName() {
+		return orgName;
+	}
+
+	public void setOrgName(String orgName) {
+		this.orgName = orgName;
+	}
+
+	public int getPerformanceCount() {
+		return performanceCount;
+	}
+
+	public void setPerformanceCount(int performanceCount) {
+		this.performanceCount = performanceCount;
+	}
+
+	public List<SimilarProduct> getSimilarProductList() {
+		return similarProductList;
+	}
+
+	public void setSimilarProductList(List<SimilarProduct> similarProductList) {
+		this.similarProductList = similarProductList;
+	}
+
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/value_list/SimilarProduct.java b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/SimilarProduct.java
new file mode 100644
index 0000000000000000000000000000000000000000..582154920e9b3d9cecf2b8c3b8adaa6b8962dca7
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/value_list/SimilarProduct.java
@@ -0,0 +1,64 @@
+package com.gx.obe.struct.value_list;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/** 
+ * @Description: EQ_ProfitRatio
+ * @author wangxiang 
+ */
+public class SimilarProduct {
+	
+	private String id;
+	
+	private String productName;
+	
+	private String productUnit;
+	
+	private int baseCount;
+	
+	private List<Goods> goodList;
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getProductName() {
+		return productName;
+	}
+
+	public void setProductName(String productName) {
+		this.productName = productName;
+	}
+
+	public String getProductUnit() {
+		return productUnit;
+	}
+
+	public void setProductUnit(String productUnit) {
+		this.productUnit = productUnit;
+	}
+
+	public int getBaseCount() {
+		return baseCount;
+	}
+
+	public void setBaseCount(int baseCount) {
+		this.baseCount = baseCount;
+	}
+
+	public List<Goods> getGoodList() {
+		return goodList;
+	}
+
+	public void setGoodList(List<Goods> goodList) {
+		this.goodList = goodList;
+	}
+	
+
+	
+}
diff --git a/com.gx.obe.struct/src/com/gx/obe/struct/widget/TabButton.java b/com.gx.obe.struct/src/com/gx/obe/struct/widget/TabButton.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc812c94c5af7d8d3f8174ff882d4a21a5d84f18
--- /dev/null
+++ b/com.gx.obe.struct/src/com/gx/obe/struct/widget/TabButton.java
@@ -0,0 +1,68 @@
+package com.gx.obe.struct.widget;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Label;
+
+import com.gx.obe.bind.prop.Prop;
+import com.gx.obe.bind.recursion.Recursions;
+import com.gx.obe.component.handler.ISelection;
+import com.swtdesigner.SWTResourceManager;
+
+public class TabButton extends Composite implements ISelection {
+	
+	private Prop<Boolean> selection = new Prop<>(false);
+	
+	private Prop<String> text = new Prop<>();
+	
+	public TabButton(Composite parent) {
+		super(parent, SWT.NONE);
+		GridLayout gridLayout = new GridLayout(1, false);
+		gridLayout.marginTop = 5;
+		gridLayout.marginHeight = 0;
+		gridLayout.marginWidth = 0;
+		setLayout(gridLayout);
+		
+		Composite composite = new Composite(this, SWT.NONE);
+		composite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		GridLayout gl_composite = new GridLayout(1, false);
+		gl_composite.marginWidth = 30;
+		gl_composite.marginHeight = 0;
+		composite.setLayout(gl_composite);
+		
+		Label lblNewLabel = new Label(composite, SWT.NONE);
+		lblNewLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
+		lblNewLabel.setFont(SWTResourceManager.getFont("Microsoft YaHei UI", 10, SWT.BOLD));
+		text.bind(lblNewLabel::setText);
+		selection.bindExe(t -> lblNewLabel.setForeground(t ? SWTResourceManager.getColor(2, 71, 191) : SWTResourceManager.getColor(0, 0, 0)));
+		
+		Label label = new Label(this, SWT.NONE);
+		GridData gd_label = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+		gd_label.heightHint = 2;
+		label.setLayoutData(gd_label);
+		selection.bindExe(t -> label.setBackground(t ? SWTResourceManager.getColor(2, 71, 191) : SWTResourceManager.getColor(SWT.COLOR_WHITE)));
+	}
+	
+	@Override
+	public void setText(String text) {
+		this.text.set(text);
+	}
+	
+	@Override
+	public void setSelection(boolean selection) {
+		this.selection.set(selection);
+	}
+	
+	@Override
+	public void addMouseListener(MouseListener mouseListener) {
+		Recursions.array((Control c) -> c instanceof Composite ? ((Composite) c).getChildren() : null).toStream(this.getChildren()).forEach(c -> c.addMouseListener(mouseListener));
+	}
+	
+	@Override
+	protected void checkSubclass() {}
+
+}