From 0d63f52d84e393204af3ba5bce86bdfddf936be8 Mon Sep 17 00:00:00 2001
From: 1821349743@qq.com <1821349743@qq.com>
Date: 星期六, 08 四月 2023 16:39:25 +0800
Subject: [PATCH] 修改报表加载返回html更改为数据

---
 src/main/java/com/product/server/report/entity/ReportEntity.java                 |  160 ++
 src/main/java/com/product/server/report/controller/DataListReportController.java |    2 
 src/main/java/com/product/server/report/service/GroupReportService.java          | 2256 ++++++++++++++++++-------------
 src/main/java/com/product/server/report/service/CommonReportService.java         | 1443 ++++++++++++-------
 src/main/java/com/product/server/report/service/DataListReportService.java       |  268 +++
 src/main/java/com/product/server/report/entity/ReportColumn.java                 |  120 +
 src/main/java/com/product/server/report/service/ReportConfigService.java         |   10 
 7 files changed, 2,789 insertions(+), 1,470 deletions(-)

diff --git a/src/main/java/com/product/server/report/controller/DataListReportController.java b/src/main/java/com/product/server/report/controller/DataListReportController.java
index 202ecf4..863f3eb 100644
--- a/src/main/java/com/product/server/report/controller/DataListReportController.java
+++ b/src/main/java/com/product/server/report/controller/DataListReportController.java
@@ -89,7 +89,7 @@
                 SpringMVCContextHolder.getSystemLogger().error(SystemCode.SYSTEM_FORM_NODATA.getValue(), SystemCode.SYSTEM_FORM_NODATA.getText());
                 return this.error(SystemCode.SYSTEM_FORM_NODATA.getValue(), SystemCode.SYSTEM_FORM_NODATA.getText());
             }
-            return BaseUtil.success(dataListReportService.getReport(fse));
+            return BaseUtil.success(dataListReportService.getReportEntity(fse));
         } catch (BaseException e) {
             SpringMVCContextHolder.getSystemLogger().error(e);
             return this.error(e.getCode(), e.getMessageInfo());
diff --git a/src/main/java/com/product/server/report/entity/ReportColumn.java b/src/main/java/com/product/server/report/entity/ReportColumn.java
new file mode 100644
index 0000000..8af08fc
--- /dev/null
+++ b/src/main/java/com/product/server/report/entity/ReportColumn.java
@@ -0,0 +1,120 @@
+package com.product.server.report.entity;
+
+import com.product.common.lang.StringUtils;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @Author cheng
+ * @Date 2023/4/3 11:34
+ * @Desc 鎶ヨ〃鍗曞厓鏍�
+ */
+public class ReportColumn {
+	//璺ㄥ垪
+	private int colspan = 1;
+	//璺ㄨ
+	private int rowspan = 1;
+	//鍗曞厓鏍煎唴瀹�
+	private String content;
+	//绌块�忓瓧娈�
+	private boolean penetrate;
+	//瀛愭姤琛�
+	private boolean subReport;
+	//绌块�忓睘鎬�
+	private String penetrateProperty;
+	//瀛愭姤琛ㄥ睘鎬�
+	private String subReportProperty;
+	//鍗曞厓鏍煎搴� px
+	private int columnWidth;
+
+	private Map<String, String> otherParams = new HashMap<>();
+
+	public void replace(String key, String value) {
+		if (!otherParams.isEmpty()) {
+			Map<String, String> otherParams = this.otherParams;
+			this.otherParams = new HashMap<>();
+			otherParams.forEach((k, v) -> {
+				this.otherParams.put(k.replace(key, value), v.replace(key, value));
+			});
+		}
+		if(!StringUtils.isEmpty(subReportProperty)){
+			subReportProperty=subReportProperty.replace(key,value);
+		}
+		if(!StringUtils.isEmpty(penetrateProperty)){
+			penetrateProperty=penetrateProperty.replace(key,value);
+		}
+		if(!StringUtils.isEmpty(content)){
+			content=content.replace(key,value);
+		}
+	}
+
+	public void addProperty(String key, String value) {
+		otherParams.put(key, value);
+	}
+
+	public int getColspan() {
+		return colspan;
+	}
+
+	public void setColspan(int colspan) {
+		this.colspan = colspan;
+	}
+
+	public int getRowspan() {
+		return rowspan;
+	}
+
+	public void setRowspan(int rowspan) {
+		this.rowspan = rowspan;
+	}
+
+	public String getContent() {
+		return content;
+	}
+
+	public void setContent(String content) {
+		this.content = content;
+	}
+
+	public boolean isPenetrate() {
+		return penetrate;
+	}
+
+	public void setPenetrate(boolean penetrate) {
+		this.penetrate = penetrate;
+	}
+
+	public boolean isSubReport() {
+		return subReport;
+	}
+
+	public void setSubReport(boolean subReport) {
+		this.subReport = subReport;
+	}
+
+	public String getPenetrateProperty() {
+		return penetrateProperty;
+	}
+
+	public void setPenetrateProperty(String penetrateProperty) {
+		this.penetrateProperty = penetrateProperty;
+	}
+
+	public String getSubReportProperty() {
+		return subReportProperty;
+	}
+
+	public void setSubReportProperty(String subReportProperty) {
+		this.subReportProperty = subReportProperty;
+	}
+
+	public int getColumnWidth() {
+		return columnWidth;
+	}
+
+	public void setColumnWidth(int columnWidth) {
+		this.columnWidth = columnWidth;
+	}
+}
diff --git a/src/main/java/com/product/server/report/entity/ReportEntity.java b/src/main/java/com/product/server/report/entity/ReportEntity.java
new file mode 100644
index 0000000..23eeec5
--- /dev/null
+++ b/src/main/java/com/product/server/report/entity/ReportEntity.java
@@ -0,0 +1,160 @@
+package com.product.server.report.entity;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.alibaba.fastjson.JSONArray;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Author cheng
+ * @Date 2023/4/3 11:33
+ * @Desc 鎶ヨ〃灞曠ず
+ */
+public class ReportEntity {
+	//鍓嶇浣跨敤
+	private String entityType = "report";
+	//澶撮儴鏍囬 锛堝寘鍚唴瀹瑰ご锛�
+	private List<List<ReportColumn>> reportHeader;
+	//鍐呭
+	private List<List<ReportColumn>> reportData;
+	//搴曢儴鏍囬
+	private List<List<ReportColumn>> reportTail;
+	//鎶ヨ〃绫诲瀷uuid
+	private String reportType;
+	//榛樿杩囨护鏉′欢
+	private Map<String, Map<String, String>> filterInfo;
+	//瀛楁淇℃伅
+	private JSONArray systemFieldMeta;
+
+
+	/************鍒嗛〉鍙傛暟*************/
+
+	private boolean isPage;
+
+	private int pageSize;
+
+	private int pageIndex;
+
+	private int totalPage;
+
+	/************鍒嗛〉鍙傛暟************
+
+
+
+	 /**
+	 * 娣诲姞涓�琛岃〃澶�
+	 *
+	 * @param reportColumnArray
+	 */
+	public void addReportHeader(List<ReportColumn> reportColumnArray) {
+		if (CollectionUtil.isEmpty(reportColumnArray)) {
+			return;
+		}
+		if (CollectionUtil.isEmpty(this.reportHeader)) {
+			reportHeader = new ArrayList<>();
+		}
+		reportHeader.add(reportColumnArray);
+	}
+
+	/**
+	 * 娣诲姞涓�琛屾暟鎹�
+	 *
+	 * @param reportDataArray
+	 */
+	private void addReportData(List<ReportColumn> reportDataArray) {
+		if (CollectionUtil.isEmpty(reportDataArray)) {
+			return;
+		}
+		if (CollectionUtil.isEmpty(this.reportData)) {
+			reportData = new ArrayList<>();
+		}
+		reportData.add(reportDataArray);
+	}
+
+
+	public String getEntityType() {
+		return entityType;
+	}
+
+	public List<List<ReportColumn>> getReportHeader() {
+		return reportHeader;
+	}
+
+	public void setReportHeader(List<List<ReportColumn>> reportHeader) {
+		this.reportHeader = reportHeader;
+	}
+
+	public List<List<ReportColumn>> getReportData() {
+		return reportData;
+	}
+
+	public void setReportData(List<List<ReportColumn>> reportData) {
+		this.reportData = reportData;
+	}
+
+	public List<List<ReportColumn>> getReportTail() {
+		return reportTail;
+	}
+
+	public void setReportTail(List<List<ReportColumn>> reportTail) {
+		this.reportTail = reportTail;
+	}
+
+	public String getReportType() {
+		return reportType;
+	}
+
+	public void setReportType(String reportType) {
+		this.reportType = reportType;
+	}
+
+	public Map<String, Map<String, String>> getFilterInfo() {
+		return filterInfo;
+	}
+
+	public void setFilterInfo(Map<String, Map<String, String>> filterInfo) {
+		this.filterInfo = filterInfo;
+	}
+
+	public JSONArray getSystemFieldMeta() {
+		return systemFieldMeta;
+	}
+
+	public void setSystemFieldMeta(JSONArray systemFieldMeta) {
+		this.systemFieldMeta = systemFieldMeta;
+	}
+
+	public boolean isPage() {
+		return isPage;
+	}
+
+	public void setPage(boolean page) {
+		isPage = page;
+	}
+
+	public int getPageSize() {
+		return pageSize;
+	}
+
+	public void setPageSize(int pageSize) {
+		this.pageSize = pageSize;
+	}
+
+	public int getPageIndex() {
+		return pageIndex;
+	}
+
+	public void setPageIndex(int pageIndex) {
+		this.pageIndex = pageIndex;
+	}
+
+	public int getTotalPage() {
+		return totalPage;
+	}
+
+	public void setTotalPage(int totalPage) {
+		this.totalPage = totalPage;
+	}
+}
diff --git a/src/main/java/com/product/server/report/service/CommonReportService.java b/src/main/java/com/product/server/report/service/CommonReportService.java
index c9c6a7e..f239244 100644
--- a/src/main/java/com/product/server/report/service/CommonReportService.java
+++ b/src/main/java/com/product/server/report/service/CommonReportService.java
@@ -1,6 +1,8 @@
 package com.product.server.report.service;
 
+import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.NumberUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -11,7 +13,10 @@
 import com.product.core.service.support.AbstractBaseService;
 import com.product.core.spring.context.SpringMVCContextHolder;
 import com.product.server.report.config.CmnConst;
+import com.product.server.report.entity.ReportColumn;
+import com.product.server.report.entity.ReportEntity;
 import com.product.util.BaseUtil;
+import com.product.util.SystemParamReplace;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -26,556 +31,940 @@
  */
 @Component
 public class CommonReportService extends AbstractBaseService {
-    @Autowired
-    private DataListReportService dataListReportService;
+	@Autowired
+	private DataListReportService dataListReportService;
 
-    /**
-     * 鎶ヨ〃-瑙f瀽
-     *
-     * @param recordDte           涓氬姟鏁版嵁dte
-     * @param totalStatisticsFlag 鏄惁鍚堣鏍囪瘑
-     * @param reportConfigMap     鎶ヨ〃閰嶇疆缂撳瓨map
-     * @param tableStyle
-     * @return
-     */
-    public JSONObject getReport(DataTableEntity recordDte, String totalName, Map<Integer, List<JSONObject>> reportConfigMap, StringBuilder tableStyle) {
-        StringBuilder reportHtml = new StringBuilder(4096);
+	/**
+	 * 鎶ヨ〃-瑙f瀽
+	 *
+	 * @param recordDte           涓氬姟鏁版嵁dte
+	 * @param totalStatisticsFlag 鏄惁鍚堣鏍囪瘑
+	 * @param reportConfigMap     鎶ヨ〃閰嶇疆缂撳瓨map
+	 * @param tableStyle
+	 * @return
+	 */
+	public ReportEntity getReportEntity(DataTableEntity recordDte, String totalName, Map<Integer, List<JSONObject>> reportConfigMap) {
+		ReportEntity report = null;
+		Map<String, Set<String>> headAndTailTitleDataMap = Maps.newHashMap();
+		// 鏁版嵁鍖�
+		report = getDataArea(reportConfigMap, headAndTailTitleDataMap, recordDte, totalName);
 
-        // css
-        StringBuilder cssHtml = dataListReportService.getCssHtml();
+		int totalColCount = reportConfigMap.get(0).size();
 
-        // 鏁版嵁鍖�
-        Map<String, Set<String>> headAndTailTitleDataMap = Maps.newHashMap();
-        String dataAreaHtml = getDataAreaHtml(reportConfigMap, headAndTailTitleDataMap, recordDte, totalName);
+		// 澶撮儴鏍囬鍖�
+		List<List<ReportColumn>> headTitleRows = null;
+		if (!reportConfigMap.get(1).isEmpty()) {
+			headTitleRows = dataListReportService.getTitle(reportConfigMap.get(1), totalColCount, headAndTailTitleDataMap, "head");
+		}
+		// 搴曢儴鏍囬鍖�
+		List<List<ReportColumn>> tailTitleRows = null;
+		if (!reportConfigMap.get(3).isEmpty()) {
+			tailTitleRows = dataListReportService.getTitle(reportConfigMap.get(3), totalColCount, headAndTailTitleDataMap, "tail");
+		}
 
-        int totalColCount = reportConfigMap.get(0).size();
-        // 澶撮儴鏍囬鍖�
-        StringBuilder headTitleHtml = null;
-        if (!reportConfigMap.get(1).isEmpty()) {
-            headTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(1), totalColCount, headAndTailTitleDataMap, "head");
-        }
+		if (!CollectionUtil.isEmpty(headTitleRows)) {
+			List<List<ReportColumn>> reportHeader = report.getReportHeader();
+			headTitleRows.addAll(reportHeader);
+			report.setReportHeader(headTitleRows);
+		}
+		if (!CollectionUtil.isEmpty(tailTitleRows)) {
+			report.setReportTail(tailTitleRows);
+		}
 
-        // 搴曢儴鏍囬鍖�
-        StringBuilder tailTitleHtml = null;
-        if (!reportConfigMap.get(3).isEmpty()) {
-            tailTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(3), totalColCount, headAndTailTitleDataMap, "tail");
-        }
 
-        reportHtml.append("\n<body>\n<table class=\"report_main\"").append(tableStyle).append(">")
-                .append(cssHtml)
-                .append(headTitleHtml == null ? "" : headTitleHtml)
-                .append(dataAreaHtml)
-                .append(tailTitleHtml == null ? "" : tailTitleHtml)
-                .append("\n</table>\n</body>");
+		return report;
+	}
 
-        JSONObject resultObj = new JSONObject();
-        resultObj.put(CmnConst.RETURN_ATTR_RESULT, true);
-        resultObj.put(CmnConst.RETURN_ATTR_MESSAGE, "鑾峰彇鎶ヨ〃鎴愬姛锛�");
-        resultObj.put(CmnConst.RETURN_ATTR_HTML, reportHtml);
-        return resultObj;
-    }
+	/**
+	 * 鎶ヨ〃-瑙f瀽
+	 *
+	 * @param recordDte           涓氬姟鏁版嵁dte
+	 * @param totalStatisticsFlag 鏄惁鍚堣鏍囪瘑
+	 * @param reportConfigMap     鎶ヨ〃閰嶇疆缂撳瓨map
+	 * @param tableStyle
+	 * @return
+	 */
+	public JSONObject getReport(DataTableEntity recordDte, String totalName, Map<Integer, List<JSONObject>> reportConfigMap, StringBuilder tableStyle) {
+		StringBuilder reportHtml = new StringBuilder(4096);
 
-    /**
-     * 鑾峰彇鎶ヨ〃鏁版嵁鍖篽tml
-     *
-     * @param reportConfigMap         鎶ヨ〃缂撳瓨map
-     * @param headAndTailTitleDataMap 澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁map
-     * @param recordDte               涓氬姟鏁版嵁闆嗗悎
-     * @param totalName               鎬昏鍚嶇О锛岄潪绌�-闇�瑕佹�昏
-     * @return
-     */
-    private String getDataAreaHtml(Map<Integer, List<JSONObject>> reportConfigMap, Map<String, Set<String>> headAndTailTitleDataMap, DataTableEntity recordDte, String totalName) {
-        // 鏁版嵁鍖哄瓧娈电紦瀛榤ap
-        Map<String, JSONObject> dataAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(0));
-        // 鑾峰彇鎸囧畾鏁版嵁闆嗕腑鍖呭惈鐨勬暟鎹尯瀛楁闆嗗悎
-        Set<String> headAndTailFieldSet = Sets.newHashSet();
-        headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(1)));
-        headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(3)));
-        // 缁熻map
-        Map<JSONObject, JSONObject> statisticsMap = Maps.newLinkedHashMap();
+		// css
+		StringBuilder cssHtml = dataListReportService.getCssHtml();
 
-        StringBuilder dataAreaHtml = new StringBuilder(1024);
-        // 鏍囬
-        dataAreaHtml.append(getDataAreaTitleHtml(dataAreaFieldConfigMap));
-        // 鍐呭
-        dataAreaHtml.append(getDataAreaDataHtml(dataAreaFieldConfigMap, recordDte, headAndTailTitleDataMap, headAndTailFieldSet, statisticsMap, totalName));
-        return dataAreaHtml.toString();
-    }
+		// 鏁版嵁鍖�
+		Map<String, Set<String>> headAndTailTitleDataMap = Maps.newHashMap();
+		String dataAreaHtml = getDataAreaHtml(reportConfigMap, headAndTailTitleDataMap, recordDte, totalName);
 
-    /**
-     * 鑾峰彇鏍囬
-     *
-     * @param dataAreaFieldConfigMap 鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @return
-     */
-    private StringBuilder getDataAreaTitleHtml(Map<String, JSONObject> dataAreaFieldConfigMap) {
-        StringBuilder html = new StringBuilder(256);
-        html.append("<tr class=\"").append(CmnConst.CLASS_TR_DATA_TITLE).append("\">");
-        dataAreaFieldConfigMap.forEach((dataAreaFieldName, dataAreaFieldConfigObj) -> {
-            html.append("<td>").append(dataListReportService.dealTdWidth(dataAreaFieldConfigObj, dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME))).append("</td>");
-        });
-        html.append("</tr>");
-        return html;
-    }
+		int totalColCount = reportConfigMap.get(0).size();
+		// 澶撮儴鏍囬鍖�
+		StringBuilder headTitleHtml = null;
+		if (!reportConfigMap.get(1).isEmpty()) {
+			headTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(1), totalColCount, headAndTailTitleDataMap, "head");
+		}
 
-    /**
-     * 鑾峰彇鍐呭锛屽寘鍚粺璁�
-     *
-     * @param dataAreaFieldConfigMap 鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param recordDte              涓氬姟鏁版嵁闆嗗悎
-     * @param headAndTailFieldSet    澶撮儴銆佸熬閮ㄦ爣棰樺尯瀛楁set
-     * @param statisticsMap          缁熻map
-     * @param totalName              鎬昏鍚嶇О
-     * @return
-     */
-    private String getDataAreaDataHtml(Map<String, JSONObject> dataAreaFieldConfigMap, DataTableEntity recordDte, Map<String, Set<String>> headAndTailTitleDataMap, Set<String> headAndTailFieldSet, Map<JSONObject, JSONObject> statisticsMap, String totalName) {
-        // 鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
-        List<String> dataAreaGroupStatisticsFieldNameList = Lists.newArrayList();
-        // 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
-        List<String> dataAreaGroupFieldNameList = Lists.newArrayList();
-        dataAreaFieldConfigMap.forEach((dataAreaFieldName, dataAreaFieldConfigObj) -> {
-            if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
-                dataAreaGroupFieldNameList.add(dataAreaFieldName);
-                if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
-                    dataAreaGroupStatisticsFieldNameList.add(dataAreaFieldName);
-                }
-            }
-        });
+		// 搴曢儴鏍囬鍖�
+		StringBuilder tailTitleHtml = null;
+		if (!reportConfigMap.get(3).isEmpty()) {
+			tailTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(3), totalColCount, headAndTailTitleDataMap, "tail");
+		}
 
-        StringBuilder dataAreaDataHtml = new StringBuilder(1024);
-        StringBuilder curRowHtml = new StringBuilder(256);
-        FieldSetEntity recordFse;
-        FieldSetEntity preFse = null;
-        String dataAreaFieldName;
-        JSONObject dataAreaFieldConfigObj;
-        String value;
-        JSONObject keyObj;
-        Map<String, String> replaceMap = Maps.newHashMap();
-        Map<String, String> dataAreaClosestGroupStatisticsFieldValueMap = Maps.newHashMap();
-        Map<String, String> dataAreaClosestGroupFieldValueMap = Maps.newHashMap();
-        String closestGroupStatisticsFieldName = null;
-        String closestGroupFieldName = null;
-        String tempFieldName;
-        String paramKey;
-        boolean combineFlag;
-        JSONObject dataAreaGroupFieldRecordObj = new JSONObject();
-        for (int i = 0; i < recordDte.getRows(); i++) {
-            recordFse = recordDte.getFieldSetEntity(i);
-            // 鑾峰彇澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁
-            dataListReportService.getHeadAndTailTitleDataMap(headAndTailTitleDataMap, headAndTailFieldSet, recordFse);
+		reportHtml.append("\n<body>\n<table class=\"report_main\"").append(tableStyle).append(">")
+				.append(cssHtml)
+				.append(headTitleHtml == null ? "" : headTitleHtml)
+				.append(dataAreaHtml)
+				.append(tailTitleHtml == null ? "" : tailTitleHtml)
+				.append("\n</table>\n</body>");
 
-            curRowHtml.setLength(0);
-            String rowUuid = IdUtil.simpleUUID();
-            curRowHtml.append("\n<tr rowIndex=\"" + (i + 1) + "\" id=\"" + rowUuid + "\" class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
-            combineFlag = true;
-            for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
-                dataAreaFieldName = entry.getKey();
-                dataAreaFieldConfigObj = entry.getValue();
-                value = dataListReportService.getValue(dataAreaFieldConfigObj, recordFse, dataAreaFieldName);
-                // 鑻ユ槸鑷畾涔夊瓧娈碉紝鍒欐斁鍏ヤ笟鍔℃暟鎹褰曚腑
-                if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD))) {
-                    recordFse.setValue(dataAreaFieldName, value);
-                }
-                if (dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
-                    int curFieldIndex = dataAreaGroupFieldNameList.indexOf(dataAreaFieldName);
-                    // 璁板綍鍒嗙粍瀛楁
-                    recordDataAreaGroupField(dataAreaGroupFieldRecordObj, dataAreaGroupFieldNameList, curFieldIndex, recordFse);
+		JSONObject resultObj = new JSONObject();
+		resultObj.put(CmnConst.RETURN_ATTR_RESULT, true);
+		resultObj.put(CmnConst.RETURN_ATTR_MESSAGE, "鑾峰彇鎶ヨ〃鎴愬姛锛�");
+		resultObj.put(CmnConst.RETURN_ATTR_HTML, reportHtml);
+		return resultObj;
+	}
 
-                    // 鍒嗙粍鍚堝瓧娈靛苟
-                    closestGroupFieldName = dataAreaFieldName;
-                    if (preFse != null && combineFlag) {
-                        if (value.equals(dataAreaClosestGroupFieldValueMap.get(closestGroupFieldName))) {
-                            dealReplaceMapAddRowspan(replaceMap, dataAreaGroupFieldNameList.subList(0, curFieldIndex + 1), preFse, true);
-                            continue;
-                        } else {
-                            combineFlag = false;
-                        }
-                    }
-                    dataAreaClosestGroupFieldValueMap.put(dataAreaFieldName, value);
-                }
-                // 鍒嗙粍缁熻
-                if (dataAreaGroupStatisticsFieldNameList.contains(dataAreaFieldName)) {
-                    int minK = dataAreaGroupStatisticsFieldNameList.size();
-                    for (int j = 0; j < dataAreaGroupStatisticsFieldNameList.size(); j++) {
-                        tempFieldName = dataAreaGroupStatisticsFieldNameList.get(j);
-                        if (!StringUtils.isEmpty(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName)) && !recordFse.getString(tempFieldName).equals(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName))) {
-                            minK = j;
-                            break;
-                        }
-                    }
-                    for (int k = dataAreaGroupStatisticsFieldNameList.size() - 1; k >= minK; k--) {
-                        tempFieldName = dataAreaGroupStatisticsFieldNameList.get(k);
-                        if (preFse != null && dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName) != null) {
-                            dataAreaDataHtml.append(getDataAreaGroupStatisticsFieldStatisticsRowHtml(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName), statisticsMap, dataAreaFieldConfigMap, tempFieldName, preFse, dataAreaGroupFieldNameList, replaceMap, dataAreaGroupFieldRecordObj));
-                            dataAreaClosestGroupStatisticsFieldValueMap.remove(tempFieldName);
-                        }
-                    }
-                    closestGroupStatisticsFieldName = dataAreaFieldName;
-                    dataAreaClosestGroupStatisticsFieldValueMap.put(dataAreaFieldName, value);
-                }
-                // 闈炲垎缁勭粺璁″瓧娈碉紙鏅��+鑷畾涔夛級
-                if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP)) && !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))) {
-                    addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value);
-                }
-                // 鑷畾涔夌粺璁″瓧娈碉紙鏈寚瀹氱粺璁$被鍨嬶紝浣跨敤鍩虹瀛楁鍏紡杩涜璁$畻锛�
-                if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD))
-                        && StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))
-                        && !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA))) {
-                    String formula = dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA);
-                    List<String> formFieldList = dataListReportService.getSuitContent(formula, CmnConst.REGEXP_FORM_FIELD);
-                    Map<String, String> formulaMap = Maps.newHashMap();
-                    boolean statisticsFlag = true;
-                    JSONObject tempObj;
-                    for (String formFieldInfo : formFieldList) {
-                        tempObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(formFieldInfo));
-                        if (tempObj == null || StringUtils.isEmpty(tempObj.getString(CmnConst.ATTR_STATISTICS))) {
-                            statisticsFlag = false;
-                            break;
-                        }
-                        formulaMap.put(formFieldInfo, tempObj.getString(CmnConst.ATTR_STATISTICS));
-                    }
-                    if (statisticsFlag) {
-                        addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value, formulaMap);
-                    }
-                }
-                if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
-                    keyObj = new JSONObject();
-                    for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
-                        keyObj.put(dataAreaGroupFieldName, recordFse.getString(dataAreaGroupFieldName));
-                        if (dataAreaGroupFieldName.equals(dataAreaFieldName)) {
-                            keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaGroupFieldName));
-                            break;
-                        }
-                    }
-                    paramKey = dataListReportService.concat(keyObj, CmnConst.ATTR_ROWSPAN);
-                    curRowHtml.append("<td rowspan=\"").append(paramKey).append("\"");
-                    replaceMap.put(paramKey, "1");
-                } else {
-                    curRowHtml.append("<td");
-                }
-                // class
-                if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
-                    curRowHtml.append(" class=\"").append(CmnConst.CLASS_TD_CAN_TURN).append("true".equals(dataAreaFieldConfigObj.getString("~isSubReport~")) ? "\"skipSubReport=true" : "\"").append(" router=\"").append(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL)).append("\"");
-                }
-                String attrValue = recordFse.getString(dataAreaFieldName + CmnConst.PROMPT_REAL_VALUE_TAIL);
-                if (StringUtils.isEmpty(attrValue)) {
-                    attrValue = recordFse.getString(dataAreaFieldName);
-                }
-                curRowHtml.append(" ").append(dataAreaFieldName).append("=\"").append(attrValue).append("\"");
-                curRowHtml.append(">");
-                // 鏍煎紡
-                value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
-                curRowHtml.append(value == null ? "" : value);
-                curRowHtml.append("</td>");
-            }
-            curRowHtml.append("\n</tr>");
-            dataAreaDataHtml.append(curRowHtml);
-            preFse = recordFse;
-        }
+	/**
+	 * 鑾峰彇鎶ヨ〃鏁版嵁鍖篽tml
+	 *
+	 * @param reportConfigMap         鎶ヨ〃缂撳瓨map
+	 * @param headAndTailTitleDataMap 澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁map
+	 * @param recordDte               涓氬姟鏁版嵁闆嗗悎
+	 * @param totalName               鎬昏鍚嶇О锛岄潪绌�-闇�瑕佹�昏
+	 * @return
+	 */
+	private String getDataAreaHtml(Map<Integer, List<JSONObject>> reportConfigMap, Map<String, Set<String>> headAndTailTitleDataMap, DataTableEntity recordDte, String totalName) {
+		// 鏁版嵁鍖哄瓧娈电紦瀛榤ap
+		Map<String, JSONObject> dataAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(0));
+		// 鑾峰彇鎸囧畾鏁版嵁闆嗕腑鍖呭惈鐨勬暟鎹尯瀛楁闆嗗悎
+		Set<String> headAndTailFieldSet = Sets.newHashSet();
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(1)));
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(3)));
+		// 缁熻map
+		Map<JSONObject, JSONObject> statisticsMap = Maps.newLinkedHashMap();
 
-        // 琛ュ叏鏈熬缁熻
-        if (!StringUtils.isEmpty(closestGroupStatisticsFieldName)) {
-            int maxK = -1;
-            for (int j = 0; j < dataAreaGroupStatisticsFieldNameList.size(); j++) {
-                tempFieldName = dataAreaGroupStatisticsFieldNameList.get(j);
-                if (closestGroupStatisticsFieldName.equals(tempFieldName)) {
-                    maxK = j;
-                }
-            }
-            for (int k = maxK; k >= 0; k--) {
-                tempFieldName = dataAreaGroupStatisticsFieldNameList.get(k);
-                if (preFse != null) {
-                    dataAreaDataHtml.append(getDataAreaGroupStatisticsFieldStatisticsRowHtml(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName), statisticsMap, dataAreaFieldConfigMap, tempFieldName, preFse, dataAreaGroupFieldNameList, replaceMap, dataAreaGroupFieldRecordObj));
-                }
-            }
-        }
+		StringBuilder dataAreaHtml = new StringBuilder(1024);
+		// 鏍囬
+		dataAreaHtml.append(getDataAreaTitleHtml(dataAreaFieldConfigMap));
+		// 鍐呭
+		dataAreaHtml.append(getDataAreaDataHtml(dataAreaFieldConfigMap, recordDte, headAndTailTitleDataMap, headAndTailFieldSet, statisticsMap, totalName));
+		return dataAreaHtml.toString();
+	}
 
-        // 鎬昏
-        if (!StringUtils.isEmpty(totalName)) {
-            dataAreaDataHtml.append(getDataAreaTotalStatisticsHtml(statisticsMap, dataAreaFieldConfigMap, dataAreaGroupFieldNameList, preFse, dataAreaGroupFieldRecordObj, totalName));
-        }
+	private ReportEntity getDataArea(Map<Integer, List<JSONObject>> reportConfigMap, Map<String, Set<String>> headAndTailTitleDataMap, DataTableEntity recordDte, String totalName) {
+		// 鏁版嵁鍖哄瓧娈电紦瀛榤ap
+		Map<String, JSONObject> dataAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(0));
+		// 鑾峰彇鎸囧畾鏁版嵁闆嗕腑鍖呭惈鐨勬暟鎹尯瀛楁闆嗗悎
+		Set<String> headAndTailFieldSet = Sets.newHashSet();
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(1)));
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(3)));
+		// 缁熻map
+		Map<JSONObject, JSONObject> statisticsMap = Maps.newLinkedHashMap();
+		List<ReportColumn> reportHeader = getReportHeader(dataAreaFieldConfigMap);
+		List<List<ReportColumn>> reportData = getReportData(dataAreaFieldConfigMap, recordDte, headAndTailTitleDataMap, headAndTailFieldSet, statisticsMap, totalName);
+		ReportEntity report = new ReportEntity();
+		report.addReportHeader(reportHeader);
+		report.setReportData(reportData);
+		return report;
+	}
 
-        String str = dataAreaDataHtml.toString();
-        for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
-            str = str.replace(entry.getKey(), entry.getValue());
-        }
+	private List<ReportColumn> getReportHeader(Map<String, JSONObject> dataAreaFieldConfigMap) {
+		if (CollectionUtil.isEmpty(dataAreaFieldConfigMap)) {
+			return null;
+		}
+		List<ReportColumn> reportColumnList = new ArrayList<>();
+		dataAreaFieldConfigMap.forEach((k, v) -> {
+			ReportColumn column = new ReportColumn();
+			column.setContent(v.getString(CmnConst.ATTR_SHOW_NAME));
+			column.setColumnWidth(NumberUtil.isNumber(v.getString(CmnConst.ATTR_WIDTH)) ? NumberUtil.parseInt(v.getString(CmnConst.ATTR_WIDTH)) : 0);
+			reportColumnList.add(column);
+		});
+		return reportColumnList;
+	}
 
-        return str;
-    }
+	private List<List<ReportColumn>> getReportData(Map<String, JSONObject> dataAreaFieldConfigMap, DataTableEntity recordDte, Map<String, Set<String>> headAndTailTitleDataMap, Set<String> headAndTailFieldSet, Map<JSONObject, JSONObject> statisticsMap, String totalName) {
+		List<List<ReportColumn>> reportData = new ArrayList<>();
+		// 鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
+		List<String> dataAreaGroupStatisticsFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+		List<String> dataAreaGroupFieldNameList = Lists.newArrayList();
+		dataAreaFieldConfigMap.forEach((dataAreaFieldName, dataAreaFieldConfigObj) -> {
+			if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+				dataAreaGroupFieldNameList.add(dataAreaFieldName);
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+					dataAreaGroupStatisticsFieldNameList.add(dataAreaFieldName);
+				}
+			}
+		});
 
-    /**
-     * 娣诲姞鍒嗙粍缁熻淇℃伅
-     * @param statisticsMap                         缁熻map
-     * @param dataAreaGroupStatisticsFieldNameList  鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
-     * @param recordFse                             涓氬姟鏁版嵁fse
-     * @param dataAreaFieldConfigObj                鏁版嵁鍖哄瓧娈祇bj
-     * @param dataAreaFieldName                     鏁版嵁鍖哄瓧娈靛悕绉�
-     * @param value                                 鍊�
-     * @param formulaMap                            鍏紡map锛屽瓧娈礽nfo鍜岀粺璁$被鍨嬬殑鏄犲皠
-     */
-    private void addStatisticsRowInfo(Map<JSONObject, JSONObject> statisticsMap, List<String> dataAreaGroupStatisticsFieldNameList, FieldSetEntity recordFse, JSONObject dataAreaFieldConfigObj, String dataAreaFieldName, String value, Map<String, String> formulaMap) {
-        JSONObject keyObj = new JSONObject();
-        keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
-        String statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
-        if (StringUtils.isEmpty(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
-            statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
-        }
-        String statisticsValue;
-        String formula = dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA);
-        JSONObject formulaFieldKeyObj = new JSONObject();
-        // 鎬昏
-        JSONObject cloneKeyObj = (JSONObject) keyObj.clone();
-        JSONObject valueObj = statisticsMap.computeIfAbsent(cloneKeyObj, k -> new JSONObject());
-        statisticsValue = getStatisticsValue(statisticsMap, formulaMap, formulaFieldKeyObj, formula, value);
-        statisticsMap.put(keyObj, dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, statisticsValue, statisticsType, true));
-        // 鍒嗙粍缁熻
-        for (String dataAreaGroupStatisticsFieldName : dataAreaGroupStatisticsFieldNameList) {
-            keyObj.put(dataAreaGroupStatisticsFieldName, recordFse.getString(dataAreaGroupStatisticsFieldName));
-            formulaFieldKeyObj.put(dataAreaGroupStatisticsFieldName, recordFse.getString(dataAreaGroupStatisticsFieldName));
-            cloneKeyObj = (JSONObject) keyObj.clone();
-            valueObj = statisticsMap.computeIfAbsent(cloneKeyObj, k -> new JSONObject());
-            statisticsValue = getStatisticsValue(statisticsMap, formulaMap, formulaFieldKeyObj, formula, value);
-            statisticsMap.put(keyObj, dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, statisticsValue, statisticsType, true));
-        }
-    }
-    private void addStatisticsRowInfo(Map<JSONObject, JSONObject> statisticsMap, List<String> dataAreaGroupStatisticsFieldNameList, FieldSetEntity recordFse, JSONObject dataAreaFieldConfigObj, String dataAreaFieldName, String value) {
-        addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value, null);
-    }
+		FieldSetEntity recordFse;
+		FieldSetEntity preFse = null;
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		String value;
+		JSONObject keyObj;
+		Map<String, String> replaceMap = Maps.newHashMap();
+		Map<String, String> dataAreaClosestGroupStatisticsFieldValueMap = Maps.newHashMap();
+		Map<String, String> dataAreaClosestGroupFieldValueMap = Maps.newHashMap();
+		String closestGroupStatisticsFieldName = null;
+		String closestGroupFieldName = null;
+		String tempFieldName;
+		String paramKey;
+		boolean combineFlag;
+		JSONObject dataAreaGroupFieldRecordObj = new JSONObject();
+		for (int i = 0; i < recordDte.getRows(); i++) {
+			recordFse = recordDte.getFieldSetEntity(i);
+			// 鑾峰彇澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁
+			dataListReportService.getHeadAndTailTitleDataMap(headAndTailTitleDataMap, headAndTailFieldSet, recordFse);
 
-    /**
-     * 鑾峰彇缁熻琛岀殑鍏紡璁$畻鍊�
-     * @param statisticsMap         缁熻map
-     * @param formulaMap            鍏紡map
-     * @param formulaFieldKeyObj    鍏紡瀛楁keyobj
-     * @param formula               鍏紡
-     * @param value                 鍘熸湰鐨勫��
-     * @return
-     */
-    private String getStatisticsValue(Map<JSONObject, JSONObject> statisticsMap, Map<String, String> formulaMap, JSONObject formulaFieldKeyObj, String formula, String value) {
-        String statisticsValue = "";
-        String formulaFieldValue;
-        if (formulaMap != null && !formulaMap.isEmpty()) {
-            for (Map.Entry<String, String> entry : formulaMap.entrySet()) {
-                formulaFieldKeyObj.put(CmnConst.ATTR_FIELD_INFO, entry.getKey());
-                formulaFieldValue = statisticsMap.get(formulaFieldKeyObj).getString(entry.getValue());
-                if (formulaFieldValue != null && formulaFieldValue.matches(CmnConst.REGEXP_NUMBER)) {
-                    formulaFieldValue += "d";
-                }
-                formula = formula.replace(entry.getKey(),  StringUtils.isEmpty(formulaFieldValue) ? "" : formulaFieldValue);
-            }
-            try {
-                statisticsValue = BaseUtil.executeExpression(formula, Maps.newHashMap()).toString();
-            } catch (Exception e) {
-                SpringMVCContextHolder.getSystemLogger().error(e);
-                statisticsValue = "";
-            }
-        }
-        return StringUtils.isEmpty(statisticsValue) ? value : statisticsValue;
-    }
+			combineFlag = true;
 
-    /**
-     * 鑾峰彇鏁版嵁鍖哄垎缁勭粺璁″瓧娈电粺璁¤html
-     *
-     * @param waitStatisticsValue         寰呯粺璁$殑鍊�
-     * @param statisticsMap               缁熻map
-     * @param dataAreaFieldConfigMap      鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param tempFieldName               鏈鎿嶄綔鐨勫瓧娈靛悕绉�
-     * @param recordFse                   涓氬姟鏁版嵁璁板綍
-     * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
-     * @param replaceMap                  鏇挎崲map
-     * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
-     * @return
-     */
-    private StringBuilder getDataAreaGroupStatisticsFieldStatisticsRowHtml(String waitStatisticsValue, Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap,
-                                                                           String tempFieldName, FieldSetEntity recordFse, List<String> dataAreaGroupFieldNameList, Map<String, String> replaceMap, JSONObject dataAreaGroupFieldRecordObj) {
-        StringBuilder html = new StringBuilder();
-        html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
-        String dataAreaFieldName;
-        JSONObject dataAreaFieldConfigObj;
-        boolean flag = false;
-        JSONObject keyObj = new JSONObject();
-        String value;
-        String statisticsType;
-        int index = 0;
-        List<String> needAddRowspanDataAreaGroupFieldNameList = Lists.newArrayList();
-        for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
-            index++;
-            dataAreaFieldName = entry.getKey();
-            if (!flag) {
-                if (dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
-                    keyObj.put(dataAreaFieldName, recordFse.getString(dataAreaFieldName));
-                    if (dataAreaFieldName.equals(tempFieldName)) {
-                        html.append("<td colspan=\"").append(dataAreaGroupFieldNameList.size() - index + 1).append("\">").append(waitStatisticsValue).append(CmnConst.STATISTICS_NAME).append("</td>");
-                        flag = true;
-                    }
-                    if (!flag) {
-                        needAddRowspanDataAreaGroupFieldNameList.add(dataAreaFieldName);
-                    }
-                }
-            } else {
-                dataAreaFieldConfigObj = entry.getValue();
-                statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
-                if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && StringUtils.isEmpty(statisticsType)) {
-                    if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
-                        html.append("<td></td>");
-                    }
-                } else {
-                    keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
-                    if (statisticsMap.get(keyObj) == null) {
-                        value = "";
-                    } else {
-                        JSONObject valueObj = statisticsMap.get(keyObj);
-                        if (StringUtils.isEmpty(statisticsType)) {
-                            statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
-                        }
-                        if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
-                            int subCnt = getAimSubCnt(keyObj, dataAreaGroupFieldNameList, dataAreaGroupFieldRecordObj);
-                            valueObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
-                            dataListReportService.getAvgValue(valueObj, dataAreaFieldConfigObj, false);
-                        }
-                        value = valueObj.getString(statisticsType);
-                    }
-                    // 鏍煎紡
-                    value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
-                    html.append("<td>").append(value == null ? "" : value).append("</td>");
-                }
-            }
-        }
-        html.append("\n</tr>");
-        dealReplaceMapAddRowspan(replaceMap, needAddRowspanDataAreaGroupFieldNameList, recordFse, false);
-        return html;
-    }
+			List<ReportColumn> columns = new ArrayList<>();
+			for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+				ReportColumn column = new ReportColumn();
+				dataAreaFieldName = entry.getKey();
+				dataAreaFieldConfigObj = entry.getValue();
+				value = dataListReportService.getValue(dataAreaFieldConfigObj, recordFse, dataAreaFieldName);
+				// 鑻ユ槸鑷畾涔夊瓧娈碉紝鍒欐斁鍏ヤ笟鍔℃暟鎹褰曚腑
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD))) {
+					recordFse.setValue(dataAreaFieldName, value);
+				}
+				if (dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
+					int curFieldIndex = dataAreaGroupFieldNameList.indexOf(dataAreaFieldName);
+					// 璁板綍鍒嗙粍瀛楁
+					recordDataAreaGroupField(dataAreaGroupFieldRecordObj, dataAreaGroupFieldNameList, curFieldIndex, recordFse);
 
-    /**
-     * 鑾峰彇鎬昏html
-     *
-     * @param statisticsMap               缁熻map
-     * @param dataAreaFieldConfigMap      鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
-     * @param preFse                      鏈�杩戞搷浣滅殑鏁版嵁fse
-     * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
-     * @param totalName                   鎬昏鍚嶇О
-     * @return
-     */
-    private String getDataAreaTotalStatisticsHtml(Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap, List<String> dataAreaGroupFieldNameList, FieldSetEntity preFse, JSONObject dataAreaGroupFieldRecordObj, String totalName) {
-        StringBuilder html = new StringBuilder(512);
-        String dataAreaFieldName;
-        JSONObject dataAreaFieldConfigObj;
-        String value;
-        JSONObject keyObj = new JSONObject();
-        String statisticsType;
-        html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
-        if (preFse == null) {
-            return html.toString();
-        }
-        int index = 0;
-        for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
-            index++;
-            dataAreaFieldName = entry.getKey();
-            if (!dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
-                dataAreaFieldConfigObj = entry.getValue();
-                statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
-                keyObj.put(CmnConst.ATTR_FIELD_INFO, dataAreaFieldConfigObj.getString(CmnConst.ATTR_FIELD_INFO));
-                if ((!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && StringUtils.isEmpty(statisticsType)) || statisticsMap.get(keyObj) == null) {
-                    value = "";
-                } else {
-                    JSONObject valueObj = statisticsMap.get(keyObj);
-                    if (StringUtils.isEmpty(statisticsType)) {
-                        statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
-                    }
-                    if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
-                        int subCnt = dataAreaGroupFieldRecordObj.size();
-                        valueObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
-                        dataListReportService.getAvgValue(valueObj, dataAreaFieldConfigObj, false);
-                    }
-                    value = valueObj.getString(statisticsType);
-                }
-                // 鏍煎紡
-                value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
-                html.append("<td>").append(value == null ? "" : value).append("</td>");
-            } else {
-                if (index == 1) {
-                    html.append("<td colspan=\"").append(dataAreaGroupFieldNameList.size()).append("\">").append(totalName).append("</td>");
-                }
-            }
-        }
-        html.append("\n</tr>");
-        return html.toString();
-    }
+					// 鍒嗙粍鍚堝瓧娈靛苟
+					closestGroupFieldName = dataAreaFieldName;
+					if (preFse != null && combineFlag) {
+						if (value.equals(dataAreaClosestGroupFieldValueMap.get(closestGroupFieldName))) {
+							dealReplaceMapAddRowspan(replaceMap, dataAreaGroupFieldNameList.subList(0, curFieldIndex + 1), preFse, true);
+							continue;
+						} else {
+							combineFlag = false;
+						}
+					}
+					dataAreaClosestGroupFieldValueMap.put(dataAreaFieldName, value);
+				}
+				// 鍒嗙粍缁熻
+				if (dataAreaGroupStatisticsFieldNameList.contains(dataAreaFieldName)) {
+					int minK = dataAreaGroupStatisticsFieldNameList.size();
+					for (int j = 0; j < dataAreaGroupStatisticsFieldNameList.size(); j++) {
+						tempFieldName = dataAreaGroupStatisticsFieldNameList.get(j);
+						if (!StringUtils.isEmpty(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName)) && !recordFse.getString(tempFieldName).equals(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName))) {
+							minK = j;
+							break;
+						}
+					}
+					for (int k = dataAreaGroupStatisticsFieldNameList.size() - 1; k >= minK; k--) {
+						tempFieldName = dataAreaGroupStatisticsFieldNameList.get(k);
+						if (preFse != null && dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName) != null) {
+							reportData.add(getDataAreaGroupStatisticsFieldStatisticsRow(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName), statisticsMap, dataAreaFieldConfigMap, tempFieldName, preFse, dataAreaGroupFieldNameList, replaceMap, dataAreaGroupFieldRecordObj));
+							dataAreaClosestGroupStatisticsFieldValueMap.remove(tempFieldName);
+						}
+					}
+					closestGroupStatisticsFieldName = dataAreaFieldName;
+					dataAreaClosestGroupStatisticsFieldValueMap.put(dataAreaFieldName, value);
+				}
+				// 闈炲垎缁勭粺璁″瓧娈碉紙鏅��+鑷畾涔夛級
+				if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP)) && !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))) {
+					addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value);
+				}
+				// 鑷畾涔夌粺璁″瓧娈碉紙鏈寚瀹氱粺璁$被鍨嬶紝浣跨敤鍩虹瀛楁鍏紡杩涜璁$畻锛�
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD))
+						&& StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))
+						&& !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA))) {
+					String formula = dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA);
+					List<String> formFieldList = dataListReportService.getSuitContent(formula, CmnConst.REGEXP_FORM_FIELD);
+					Map<String, String> formulaMap = Maps.newHashMap();
+					boolean statisticsFlag = true;
+					JSONObject tempObj;
+					for (String formFieldInfo : formFieldList) {
+						tempObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(formFieldInfo));
+						if (tempObj == null || StringUtils.isEmpty(tempObj.getString(CmnConst.ATTR_STATISTICS))) {
+							statisticsFlag = false;
+							break;
+						}
+						formulaMap.put(formFieldInfo, tempObj.getString(CmnConst.ATTR_STATISTICS));
+					}
+					if (statisticsFlag) {
+						addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value, formulaMap);
+					}
+				}
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+					keyObj = new JSONObject();
+					for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
+						keyObj.put(dataAreaGroupFieldName, recordFse.getString(dataAreaGroupFieldName));
+						if (dataAreaGroupFieldName.equals(dataAreaFieldName)) {
+							keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaGroupFieldName));
+							break;
+						}
+					}
+					paramKey = dataListReportService.concat(keyObj, CmnConst.ATTR_ROWSPAN);
+					column.setRowspan(NumberUtil.parseInt(paramKey));
+					replaceMap.put(paramKey, "1");
+				}
+				// class
+				if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
+					//瀛愭姤琛�
+					String url = dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL);
+					url = SystemParamReplace.replaceParams(url, recordFse);
+					column.setSubReport("true".equals(dataAreaFieldConfigObj.getString("~isSubReport~")));
+					if (!column.isSubReport()) {
+						column.setPenetrate(true);
+						column.setPenetrateProperty(url);
+					} else {
+						column.setSubReportProperty(url);
+					}
+				}
+				String attrValue = recordFse.getString(dataAreaFieldName + CmnConst.PROMPT_REAL_VALUE_TAIL);
+				if (StringUtils.isEmpty(attrValue)) {
+					attrValue = recordFse.getString(dataAreaFieldName);
+				}
+				column.addProperty(dataAreaFieldName, attrValue);
+				// 鏍煎紡
+				value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+				column.setContent(value);
+				columns.add(column);
+			}
+			reportData.add(columns);
+			preFse = recordFse;
+		}
 
-    /**
-     * 澶勭悊鍙傛暟鏇挎崲map-娣诲姞鏁版嵁鍖哄垎缁勫瓧娈电殑鍗犺
-     *
-     * @param replaceMap                            鏇挎崲map
-     * @param needAddRowspanDataAreaGroupFieldNames 闇�瑕佹坊鍔犲崰琛岀殑鏁版嵁鍖哄垎缁勫瓧娈靛悕绉伴泦鍚�
-     * @param recordFse                             涓氬姟鏁版嵁璁板綍
-     */
-    private void dealReplaceMapAddRowspan(Map<String, String> replaceMap, Collection<String> needAddRowspanDataAreaGroupFieldNames, FieldSetEntity recordFse, boolean commonFieldFlag) {
-        JSONObject keyObj = new JSONObject();
-        String value;
-        int rowspan;
-        String paramKey;
-        int index = 0;
-        for (String fieldName : needAddRowspanDataAreaGroupFieldNames) {
-            index++;
-            keyObj.put(fieldName, recordFse.getString(fieldName));
-            if (commonFieldFlag && index != needAddRowspanDataAreaGroupFieldNames.size()) {
-                continue;
-            }
-            keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(fieldName));
-            paramKey = dataListReportService.concat(keyObj, CmnConst.ATTR_ROWSPAN);
-            value = replaceMap.get(paramKey);
-            rowspan = StringUtils.isEmpty(value) ? 1 : Integer.parseInt(value) + 1;
-            replaceMap.put(paramKey, String.valueOf(rowspan));
-        }
-    }
+		// 琛ュ叏鏈熬缁熻
+		if (!StringUtils.isEmpty(closestGroupStatisticsFieldName)) {
+			int maxK = -1;
+			for (int j = 0; j < dataAreaGroupStatisticsFieldNameList.size(); j++) {
+				tempFieldName = dataAreaGroupStatisticsFieldNameList.get(j);
+				if (closestGroupStatisticsFieldName.equals(tempFieldName)) {
+					maxK = j;
+				}
+			}
+			for (int k = maxK; k >= 0; k--) {
+				tempFieldName = dataAreaGroupStatisticsFieldNameList.get(k);
+				if (preFse != null) {
+					reportData.add(getDataAreaGroupStatisticsFieldStatisticsRow(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName), statisticsMap, dataAreaFieldConfigMap, tempFieldName, preFse, dataAreaGroupFieldNameList, replaceMap, dataAreaGroupFieldRecordObj));
+				}
+			}
+		}
 
-    /**
-     * 璁板綍鍒嗙粍瀛楁
-     *
-     * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
-     * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
-     * @param curFieldIndex               褰撳墠瀛楁涓嬫爣
-     * @param recordFse                   涓氬姟鏁版嵁璁板綍
-     */
-    private void recordDataAreaGroupField(JSONObject dataAreaGroupFieldRecordObj, List<String> dataAreaGroupFieldNameList, int curFieldIndex, FieldSetEntity recordFse) {
-        String tempFieldName;
-        JSONObject parentObj = dataAreaGroupFieldRecordObj;
-        JSONObject subObj;
-        String value;
-        for (int j = 0; j <= curFieldIndex; j++) {
-            tempFieldName = dataAreaGroupFieldNameList.get(j);
-            value = recordFse.getString(tempFieldName);
-            subObj = parentObj.getJSONObject(value);
-            if (subObj == null) {
-                subObj = new JSONObject();
-                parentObj.put(value, subObj);
-            }
-            parentObj = subObj;
-        }
-    }
+		// 鎬昏
+		if (!StringUtils.isEmpty(totalName)) {
+			reportData.add(getDataAreaTotalStatistics(statisticsMap, dataAreaFieldConfigMap, dataAreaGroupFieldNameList, preFse, dataAreaGroupFieldRecordObj, totalName));
+		}
+		for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
+			reportData.stream().forEach(item -> {
+				item.stream().forEach(column -> {
+					column.replace(entry.getKey(), entry.getValue());
+				});
+			});
+		}
 
-    /**
-     * 鑾峰彇鎸囧畾鐨勪笅绾у垎缁勯」
-     *
-     * @param keyObj                      鎸囧畾鐨刱ey
-     * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
-     * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
-     * @return
-     */
-    private int getAimSubCnt(JSONObject keyObj, List<String> dataAreaGroupFieldNameList, JSONObject dataAreaGroupFieldRecordObj) {
-        String value;
-        JSONObject parentObj = dataAreaGroupFieldRecordObj;
-        JSONObject subObj = null;
-        for (String fieldName : dataAreaGroupFieldNameList) {
-            value = keyObj.getString(fieldName);
-            if (value != null) {
-                subObj = parentObj.getJSONObject(value);
-            } else {
-                break;
-            }
-            parentObj = subObj;
-        }
-        return subObj == null ? 0 : subObj.size();
-    }
+		return reportData;
+	}
+
+	/**
+	 * 鑾峰彇鎬昏琛�
+	 *
+	 * @param statisticsMap               缁熻map
+	 * @param dataAreaFieldConfigMap      鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+	 * @param preFse                      鏈�杩戞搷浣滅殑鏁版嵁fse
+	 * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
+	 * @param totalName                   鎬昏鍚嶇О
+	 * @return
+	 */
+	private List<ReportColumn> getDataAreaTotalStatistics(Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap, List<String> dataAreaGroupFieldNameList, FieldSetEntity preFse, JSONObject dataAreaGroupFieldRecordObj, String totalName) {
+		List<ReportColumn> columns = new ArrayList<>();
+//		StringBuilder html = new StringBuilder(512);
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		String value;
+		JSONObject keyObj = new JSONObject();
+		String statisticsType;
+//		html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
+		if (preFse == null) {
+			return null;
+		}
+		int index = 0;
+		for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+			ReportColumn column = new ReportColumn();
+			index++;
+			dataAreaFieldName = entry.getKey();
+			if (!dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
+				dataAreaFieldConfigObj = entry.getValue();
+				statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+				keyObj.put(CmnConst.ATTR_FIELD_INFO, dataAreaFieldConfigObj.getString(CmnConst.ATTR_FIELD_INFO));
+				if ((!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && StringUtils.isEmpty(statisticsType)) || statisticsMap.get(keyObj) == null) {
+					value = "";
+				} else {
+					JSONObject valueObj = statisticsMap.get(keyObj);
+					if (StringUtils.isEmpty(statisticsType)) {
+						statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
+					}
+					if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
+						int subCnt = dataAreaGroupFieldRecordObj.size();
+						valueObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
+						dataListReportService.getAvgValue(valueObj, dataAreaFieldConfigObj, false);
+					}
+					value = valueObj.getString(statisticsType);
+				}
+				// 鏍煎紡
+				value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+				column.setContent(value);
+//				html.append("<td>").append(value == null ? "" : value).append("</td>");
+			} else {
+				if (index == 1) {
+					column.setColspan(dataAreaGroupFieldNameList.size());
+					column.setContent(totalName);
+//					html.append("<td colspan=\"").append(dataAreaGroupFieldNameList.size()).append("\">").append(totalName).append("</td>");
+				}
+			}
+			columns.add(column);
+		}
+//		html.append("\n</tr>");
+		return columns;
+	}
+
+	private List<ReportColumn> getDataAreaGroupStatisticsFieldStatisticsRow(String waitStatisticsValue, Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap,
+																			String tempFieldName, FieldSetEntity recordFse, List<String> dataAreaGroupFieldNameList, Map<String, String> replaceMap, JSONObject dataAreaGroupFieldRecordObj) {
+		List<ReportColumn> columns = new ArrayList<>();
+//		StringBuilder html = new StringBuilder();
+//		html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		boolean flag = false;
+		JSONObject keyObj = new JSONObject();
+		String value;
+		String statisticsType;
+		int index = 0;
+		List<String> needAddRowspanDataAreaGroupFieldNameList = Lists.newArrayList();
+		for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+			ReportColumn column = new ReportColumn();
+			index++;
+			dataAreaFieldName = entry.getKey();
+			if (!flag) {
+				if (dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
+					keyObj.put(dataAreaFieldName, recordFse.getString(dataAreaFieldName));
+					if (dataAreaFieldName.equals(tempFieldName)) {
+						column.setColspan(dataAreaGroupFieldNameList.size() - index + 1);
+						column.setContent(waitStatisticsValue + CmnConst.STATISTICS_NAME);
+					}
+					if (!flag) {
+						needAddRowspanDataAreaGroupFieldNameList.add(dataAreaFieldName);
+					}
+				}
+			} else {
+				dataAreaFieldConfigObj = entry.getValue();
+				statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+				if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && StringUtils.isEmpty(statisticsType)) {
+					if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+//						html.append("<td></td>");
+					}
+				} else {
+					keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+					if (statisticsMap.get(keyObj) == null) {
+						value = "";
+					} else {
+						JSONObject valueObj = statisticsMap.get(keyObj);
+						if (StringUtils.isEmpty(statisticsType)) {
+							statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
+						}
+						if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
+							int subCnt = getAimSubCnt(keyObj, dataAreaGroupFieldNameList, dataAreaGroupFieldRecordObj);
+							valueObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
+							dataListReportService.getAvgValue(valueObj, dataAreaFieldConfigObj, false);
+						}
+						value = valueObj.getString(statisticsType);
+					}
+					// 鏍煎紡
+					value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+					column.setContent(value);
+//					html.append("<td>").append(value == null ? "" : value).append("</td>");
+				}
+			}
+			columns.add(column);
+		}
+//		html.append("\n</tr>");
+		dealReplaceMapAddRowspan(replaceMap, needAddRowspanDataAreaGroupFieldNameList, recordFse, false);
+		return null;
+	}
+
+
+	/**
+	 * 鑾峰彇鏍囬
+	 *
+	 * @param dataAreaFieldConfigMap 鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @return
+	 */
+	private StringBuilder getDataAreaTitleHtml(Map<String, JSONObject> dataAreaFieldConfigMap) {
+		StringBuilder html = new StringBuilder(256);
+		html.append("<tr class=\"").append(CmnConst.CLASS_TR_DATA_TITLE).append("\">");
+		dataAreaFieldConfigMap.forEach((dataAreaFieldName, dataAreaFieldConfigObj) -> {
+			html.append("<td>").append(dataListReportService.dealTdWidth(dataAreaFieldConfigObj, dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME))).append("</td>");
+		});
+		html.append("</tr>");
+		return html;
+	}
+
+	/**
+	 * 鑾峰彇鍐呭锛屽寘鍚粺璁�
+	 *
+	 * @param dataAreaFieldConfigMap 鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param recordDte              涓氬姟鏁版嵁闆嗗悎
+	 * @param headAndTailFieldSet    澶撮儴銆佸熬閮ㄦ爣棰樺尯瀛楁set
+	 * @param statisticsMap          缁熻map
+	 * @param totalName              鎬昏鍚嶇О
+	 * @return
+	 */
+	private String getDataAreaDataHtml(Map<String, JSONObject> dataAreaFieldConfigMap, DataTableEntity recordDte, Map<String, Set<String>> headAndTailTitleDataMap, Set<String> headAndTailFieldSet, Map<JSONObject, JSONObject> statisticsMap, String totalName) {
+		// 鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
+		List<String> dataAreaGroupStatisticsFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+		List<String> dataAreaGroupFieldNameList = Lists.newArrayList();
+		dataAreaFieldConfigMap.forEach((dataAreaFieldName, dataAreaFieldConfigObj) -> {
+			if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+				dataAreaGroupFieldNameList.add(dataAreaFieldName);
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+					dataAreaGroupStatisticsFieldNameList.add(dataAreaFieldName);
+				}
+			}
+		});
+
+		StringBuilder dataAreaDataHtml = new StringBuilder(1024);
+		StringBuilder curRowHtml = new StringBuilder(256);
+		FieldSetEntity recordFse;
+		FieldSetEntity preFse = null;
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		String value;
+		JSONObject keyObj;
+		Map<String, String> replaceMap = Maps.newHashMap();
+		Map<String, String> dataAreaClosestGroupStatisticsFieldValueMap = Maps.newHashMap();
+		Map<String, String> dataAreaClosestGroupFieldValueMap = Maps.newHashMap();
+		String closestGroupStatisticsFieldName = null;
+		String closestGroupFieldName = null;
+		String tempFieldName;
+		String paramKey;
+		boolean combineFlag;
+		JSONObject dataAreaGroupFieldRecordObj = new JSONObject();
+		for (int i = 0; i < recordDte.getRows(); i++) {
+			recordFse = recordDte.getFieldSetEntity(i);
+			// 鑾峰彇澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁
+			dataListReportService.getHeadAndTailTitleDataMap(headAndTailTitleDataMap, headAndTailFieldSet, recordFse);
+
+			curRowHtml.setLength(0);
+			String rowUuid = IdUtil.simpleUUID();
+			curRowHtml.append("\n<tr rowIndex=\"" + (i + 1) + "\" id=\"" + rowUuid + "\" class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
+			combineFlag = true;
+			for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+				dataAreaFieldName = entry.getKey();
+				dataAreaFieldConfigObj = entry.getValue();
+				value = dataListReportService.getValue(dataAreaFieldConfigObj, recordFse, dataAreaFieldName);
+				// 鑻ユ槸鑷畾涔夊瓧娈碉紝鍒欐斁鍏ヤ笟鍔℃暟鎹褰曚腑
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD))) {
+					recordFse.setValue(dataAreaFieldName, value);
+				}
+				if (dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
+					int curFieldIndex = dataAreaGroupFieldNameList.indexOf(dataAreaFieldName);
+					// 璁板綍鍒嗙粍瀛楁
+					recordDataAreaGroupField(dataAreaGroupFieldRecordObj, dataAreaGroupFieldNameList, curFieldIndex, recordFse);
+
+					// 鍒嗙粍鍚堝瓧娈靛苟
+					closestGroupFieldName = dataAreaFieldName;
+					if (preFse != null && combineFlag) {
+						if (value.equals(dataAreaClosestGroupFieldValueMap.get(closestGroupFieldName))) {
+							dealReplaceMapAddRowspan(replaceMap, dataAreaGroupFieldNameList.subList(0, curFieldIndex + 1), preFse, true);
+							continue;
+						} else {
+							combineFlag = false;
+						}
+					}
+					dataAreaClosestGroupFieldValueMap.put(dataAreaFieldName, value);
+				}
+				// 鍒嗙粍缁熻
+				if (dataAreaGroupStatisticsFieldNameList.contains(dataAreaFieldName)) {
+					int minK = dataAreaGroupStatisticsFieldNameList.size();
+					for (int j = 0; j < dataAreaGroupStatisticsFieldNameList.size(); j++) {
+						tempFieldName = dataAreaGroupStatisticsFieldNameList.get(j);
+						if (!StringUtils.isEmpty(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName)) && !recordFse.getString(tempFieldName).equals(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName))) {
+							minK = j;
+							break;
+						}
+					}
+					for (int k = dataAreaGroupStatisticsFieldNameList.size() - 1; k >= minK; k--) {
+						tempFieldName = dataAreaGroupStatisticsFieldNameList.get(k);
+						if (preFse != null && dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName) != null) {
+							dataAreaDataHtml.append(getDataAreaGroupStatisticsFieldStatisticsRowHtml(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName), statisticsMap, dataAreaFieldConfigMap, tempFieldName, preFse, dataAreaGroupFieldNameList, replaceMap, dataAreaGroupFieldRecordObj));
+							dataAreaClosestGroupStatisticsFieldValueMap.remove(tempFieldName);
+						}
+					}
+					closestGroupStatisticsFieldName = dataAreaFieldName;
+					dataAreaClosestGroupStatisticsFieldValueMap.put(dataAreaFieldName, value);
+				}
+				// 闈炲垎缁勭粺璁″瓧娈碉紙鏅��+鑷畾涔夛級
+				if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP)) && !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))) {
+					addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value);
+				}
+				// 鑷畾涔夌粺璁″瓧娈碉紙鏈寚瀹氱粺璁$被鍨嬶紝浣跨敤鍩虹瀛楁鍏紡杩涜璁$畻锛�
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD))
+						&& StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))
+						&& !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA))) {
+					String formula = dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA);
+					List<String> formFieldList = dataListReportService.getSuitContent(formula, CmnConst.REGEXP_FORM_FIELD);
+					Map<String, String> formulaMap = Maps.newHashMap();
+					boolean statisticsFlag = true;
+					JSONObject tempObj;
+					for (String formFieldInfo : formFieldList) {
+						tempObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(formFieldInfo));
+						if (tempObj == null || StringUtils.isEmpty(tempObj.getString(CmnConst.ATTR_STATISTICS))) {
+							statisticsFlag = false;
+							break;
+						}
+						formulaMap.put(formFieldInfo, tempObj.getString(CmnConst.ATTR_STATISTICS));
+					}
+					if (statisticsFlag) {
+						addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value, formulaMap);
+					}
+				}
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+					keyObj = new JSONObject();
+					for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
+						keyObj.put(dataAreaGroupFieldName, recordFse.getString(dataAreaGroupFieldName));
+						if (dataAreaGroupFieldName.equals(dataAreaFieldName)) {
+							keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaGroupFieldName));
+							break;
+						}
+					}
+					paramKey = dataListReportService.concat(keyObj, CmnConst.ATTR_ROWSPAN);
+					curRowHtml.append("<td rowspan=\"").append(paramKey).append("\"");
+					replaceMap.put(paramKey, "1");
+				} else {
+					curRowHtml.append("<td");
+				}
+				// class
+				if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
+					curRowHtml.append(" class=\"").append(CmnConst.CLASS_TD_CAN_TURN).append("true".equals(dataAreaFieldConfigObj.getString("~isSubReport~")) ? "\"skipSubReport=true" : "\"").append(" router=\"").append(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL)).append("\"");
+				}
+				String attrValue = recordFse.getString(dataAreaFieldName + CmnConst.PROMPT_REAL_VALUE_TAIL);
+				if (StringUtils.isEmpty(attrValue)) {
+					attrValue = recordFse.getString(dataAreaFieldName);
+				}
+				curRowHtml.append(" ").append(dataAreaFieldName).append("=\"").append(attrValue).append("\"");
+				curRowHtml.append(">");
+				// 鏍煎紡
+				value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+				curRowHtml.append(value == null ? "" : value);
+				curRowHtml.append("</td>");
+			}
+			curRowHtml.append("\n</tr>");
+			dataAreaDataHtml.append(curRowHtml);
+			preFse = recordFse;
+		}
+
+		// 琛ュ叏鏈熬缁熻
+		if (!StringUtils.isEmpty(closestGroupStatisticsFieldName)) {
+			int maxK = -1;
+			for (int j = 0; j < dataAreaGroupStatisticsFieldNameList.size(); j++) {
+				tempFieldName = dataAreaGroupStatisticsFieldNameList.get(j);
+				if (closestGroupStatisticsFieldName.equals(tempFieldName)) {
+					maxK = j;
+				}
+			}
+			for (int k = maxK; k >= 0; k--) {
+				tempFieldName = dataAreaGroupStatisticsFieldNameList.get(k);
+				if (preFse != null) {
+					dataAreaDataHtml.append(getDataAreaGroupStatisticsFieldStatisticsRowHtml(dataAreaClosestGroupStatisticsFieldValueMap.get(tempFieldName), statisticsMap, dataAreaFieldConfigMap, tempFieldName, preFse, dataAreaGroupFieldNameList, replaceMap, dataAreaGroupFieldRecordObj));
+				}
+			}
+		}
+
+		// 鎬昏
+		if (!StringUtils.isEmpty(totalName)) {
+			dataAreaDataHtml.append(getDataAreaTotalStatisticsHtml(statisticsMap, dataAreaFieldConfigMap, dataAreaGroupFieldNameList, preFse, dataAreaGroupFieldRecordObj, totalName));
+		}
+
+		String str = dataAreaDataHtml.toString();
+		for (Map.Entry<String, String> entry : replaceMap.entrySet()) {
+			str = str.replace(entry.getKey(), entry.getValue());
+		}
+
+		return str;
+	}
+
+	/**
+	 * 娣诲姞鍒嗙粍缁熻淇℃伅
+	 *
+	 * @param statisticsMap                        缁熻map
+	 * @param dataAreaGroupStatisticsFieldNameList 鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
+	 * @param recordFse                            涓氬姟鏁版嵁fse
+	 * @param dataAreaFieldConfigObj               鏁版嵁鍖哄瓧娈祇bj
+	 * @param dataAreaFieldName                    鏁版嵁鍖哄瓧娈靛悕绉�
+	 * @param value                                鍊�
+	 * @param formulaMap                           鍏紡map锛屽瓧娈礽nfo鍜岀粺璁$被鍨嬬殑鏄犲皠
+	 */
+	private void addStatisticsRowInfo(Map<JSONObject, JSONObject> statisticsMap, List<String> dataAreaGroupStatisticsFieldNameList, FieldSetEntity recordFse, JSONObject dataAreaFieldConfigObj, String dataAreaFieldName, String value, Map<String, String> formulaMap) {
+		JSONObject keyObj = new JSONObject();
+		keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+		String statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+		if (StringUtils.isEmpty(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+			statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
+		}
+		String statisticsValue;
+		String formula = dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA);
+		JSONObject formulaFieldKeyObj = new JSONObject();
+		// 鎬昏
+		JSONObject cloneKeyObj = (JSONObject) keyObj.clone();
+		JSONObject valueObj = statisticsMap.computeIfAbsent(cloneKeyObj, k -> new JSONObject());
+		statisticsValue = getStatisticsValue(statisticsMap, formulaMap, formulaFieldKeyObj, formula, value);
+		statisticsMap.put(keyObj, dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, statisticsValue, statisticsType, true));
+		// 鍒嗙粍缁熻
+		for (String dataAreaGroupStatisticsFieldName : dataAreaGroupStatisticsFieldNameList) {
+			keyObj.put(dataAreaGroupStatisticsFieldName, recordFse.getString(dataAreaGroupStatisticsFieldName));
+			formulaFieldKeyObj.put(dataAreaGroupStatisticsFieldName, recordFse.getString(dataAreaGroupStatisticsFieldName));
+			cloneKeyObj = (JSONObject) keyObj.clone();
+			valueObj = statisticsMap.computeIfAbsent(cloneKeyObj, k -> new JSONObject());
+			statisticsValue = getStatisticsValue(statisticsMap, formulaMap, formulaFieldKeyObj, formula, value);
+			statisticsMap.put(keyObj, dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, statisticsValue, statisticsType, true));
+		}
+	}
+
+	private void addStatisticsRowInfo(Map<JSONObject, JSONObject> statisticsMap, List<String> dataAreaGroupStatisticsFieldNameList, FieldSetEntity recordFse, JSONObject dataAreaFieldConfigObj, String dataAreaFieldName, String value) {
+		addStatisticsRowInfo(statisticsMap, dataAreaGroupStatisticsFieldNameList, recordFse, dataAreaFieldConfigObj, dataAreaFieldName, value, null);
+	}
+
+	/**
+	 * 鑾峰彇缁熻琛岀殑鍏紡璁$畻鍊�
+	 *
+	 * @param statisticsMap      缁熻map
+	 * @param formulaMap         鍏紡map
+	 * @param formulaFieldKeyObj 鍏紡瀛楁keyobj
+	 * @param formula            鍏紡
+	 * @param value              鍘熸湰鐨勫��
+	 * @return
+	 */
+	private String getStatisticsValue(Map<JSONObject, JSONObject> statisticsMap, Map<String, String> formulaMap, JSONObject formulaFieldKeyObj, String formula, String value) {
+		String statisticsValue = "";
+		String formulaFieldValue;
+		if (formulaMap != null && !formulaMap.isEmpty()) {
+			for (Map.Entry<String, String> entry : formulaMap.entrySet()) {
+				formulaFieldKeyObj.put(CmnConst.ATTR_FIELD_INFO, entry.getKey());
+				formulaFieldValue = statisticsMap.get(formulaFieldKeyObj).getString(entry.getValue());
+				if (formulaFieldValue != null && formulaFieldValue.matches(CmnConst.REGEXP_NUMBER)) {
+					formulaFieldValue += "d";
+				}
+				formula = formula.replace(entry.getKey(), StringUtils.isEmpty(formulaFieldValue) ? "" : formulaFieldValue);
+			}
+			try {
+				statisticsValue = BaseUtil.executeExpression(formula, Maps.newHashMap()).toString();
+			} catch (Exception e) {
+				SpringMVCContextHolder.getSystemLogger().error(e);
+				statisticsValue = "";
+			}
+		}
+		return StringUtils.isEmpty(statisticsValue) ? value : statisticsValue;
+	}
+
+	/**
+	 * 鑾峰彇鏁版嵁鍖哄垎缁勭粺璁″瓧娈电粺璁¤html
+	 *
+	 * @param waitStatisticsValue         寰呯粺璁$殑鍊�
+	 * @param statisticsMap               缁熻map
+	 * @param dataAreaFieldConfigMap      鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param tempFieldName               鏈鎿嶄綔鐨勫瓧娈靛悕绉�
+	 * @param recordFse                   涓氬姟鏁版嵁璁板綍
+	 * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+	 * @param replaceMap                  鏇挎崲map
+	 * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
+	 * @return
+	 */
+	private StringBuilder getDataAreaGroupStatisticsFieldStatisticsRowHtml(String waitStatisticsValue, Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap,
+																		   String tempFieldName, FieldSetEntity recordFse, List<String> dataAreaGroupFieldNameList, Map<String, String> replaceMap, JSONObject dataAreaGroupFieldRecordObj) {
+		StringBuilder html = new StringBuilder();
+		html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		boolean flag = false;
+		JSONObject keyObj = new JSONObject();
+		String value;
+		String statisticsType;
+		int index = 0;
+		List<String> needAddRowspanDataAreaGroupFieldNameList = Lists.newArrayList();
+		for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+			index++;
+			dataAreaFieldName = entry.getKey();
+			if (!flag) {
+				if (dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
+					keyObj.put(dataAreaFieldName, recordFse.getString(dataAreaFieldName));
+					if (dataAreaFieldName.equals(tempFieldName)) {
+						html.append("<td colspan=\"").append(dataAreaGroupFieldNameList.size() - index + 1).append("\">").append(waitStatisticsValue).append(CmnConst.STATISTICS_NAME).append("</td>");
+						flag = true;
+					}
+					if (!flag) {
+						needAddRowspanDataAreaGroupFieldNameList.add(dataAreaFieldName);
+					}
+				}
+			} else {
+				dataAreaFieldConfigObj = entry.getValue();
+				statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+				if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && StringUtils.isEmpty(statisticsType)) {
+					if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+						html.append("<td></td>");
+					}
+				} else {
+					keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+					if (statisticsMap.get(keyObj) == null) {
+						value = "";
+					} else {
+						JSONObject valueObj = statisticsMap.get(keyObj);
+						if (StringUtils.isEmpty(statisticsType)) {
+							statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
+						}
+						if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
+							int subCnt = getAimSubCnt(keyObj, dataAreaGroupFieldNameList, dataAreaGroupFieldRecordObj);
+							valueObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
+							dataListReportService.getAvgValue(valueObj, dataAreaFieldConfigObj, false);
+						}
+						value = valueObj.getString(statisticsType);
+					}
+					// 鏍煎紡
+					value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+					html.append("<td>").append(value == null ? "" : value).append("</td>");
+				}
+			}
+		}
+		html.append("\n</tr>");
+		dealReplaceMapAddRowspan(replaceMap, needAddRowspanDataAreaGroupFieldNameList, recordFse, false);
+		return html;
+	}
+
+	/**
+	 * 鑾峰彇鎬昏html
+	 *
+	 * @param statisticsMap               缁熻map
+	 * @param dataAreaFieldConfigMap      鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+	 * @param preFse                      鏈�杩戞搷浣滅殑鏁版嵁fse
+	 * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
+	 * @param totalName                   鎬昏鍚嶇О
+	 * @return
+	 */
+	private String getDataAreaTotalStatisticsHtml(Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap, List<String> dataAreaGroupFieldNameList, FieldSetEntity preFse, JSONObject dataAreaGroupFieldRecordObj, String totalName) {
+		StringBuilder html = new StringBuilder(512);
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		String value;
+		JSONObject keyObj = new JSONObject();
+		String statisticsType;
+		html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
+		if (preFse == null) {
+			return html.toString();
+		}
+		int index = 0;
+		for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+			index++;
+			dataAreaFieldName = entry.getKey();
+			if (!dataAreaGroupFieldNameList.contains(dataAreaFieldName)) {
+				dataAreaFieldConfigObj = entry.getValue();
+				statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+				keyObj.put(CmnConst.ATTR_FIELD_INFO, dataAreaFieldConfigObj.getString(CmnConst.ATTR_FIELD_INFO));
+				if ((!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && StringUtils.isEmpty(statisticsType)) || statisticsMap.get(keyObj) == null) {
+					value = "";
+				} else {
+					JSONObject valueObj = statisticsMap.get(keyObj);
+					if (StringUtils.isEmpty(statisticsType)) {
+						statisticsType = CmnConst.ATTR_STATISTICS_DEFAULT;
+					}
+					if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
+						int subCnt = dataAreaGroupFieldRecordObj.size();
+						valueObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
+						dataListReportService.getAvgValue(valueObj, dataAreaFieldConfigObj, false);
+					}
+					value = valueObj.getString(statisticsType);
+				}
+				// 鏍煎紡
+				value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+				html.append("<td>").append(value == null ? "" : value).append("</td>");
+			} else {
+				if (index == 1) {
+					html.append("<td colspan=\"").append(dataAreaGroupFieldNameList.size()).append("\">").append(totalName).append("</td>");
+				}
+			}
+		}
+		html.append("\n</tr>");
+		return html.toString();
+	}
+
+	/**
+	 * 澶勭悊鍙傛暟鏇挎崲map-娣诲姞鏁版嵁鍖哄垎缁勫瓧娈电殑鍗犺
+	 *
+	 * @param replaceMap                            鏇挎崲map
+	 * @param needAddRowspanDataAreaGroupFieldNames 闇�瑕佹坊鍔犲崰琛岀殑鏁版嵁鍖哄垎缁勫瓧娈靛悕绉伴泦鍚�
+	 * @param recordFse                             涓氬姟鏁版嵁璁板綍
+	 */
+	private void dealReplaceMapAddRowspan(Map<String, String> replaceMap, Collection<String> needAddRowspanDataAreaGroupFieldNames, FieldSetEntity recordFse, boolean commonFieldFlag) {
+		JSONObject keyObj = new JSONObject();
+		String value;
+		int rowspan;
+		String paramKey;
+		int index = 0;
+		for (String fieldName : needAddRowspanDataAreaGroupFieldNames) {
+			index++;
+			keyObj.put(fieldName, recordFse.getString(fieldName));
+			if (commonFieldFlag && index != needAddRowspanDataAreaGroupFieldNames.size()) {
+				continue;
+			}
+			keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(fieldName));
+			paramKey = dataListReportService.concat(keyObj, CmnConst.ATTR_ROWSPAN);
+			value = replaceMap.get(paramKey);
+			rowspan = StringUtils.isEmpty(value) ? 1 : Integer.parseInt(value) + 1;
+			replaceMap.put(paramKey, String.valueOf(rowspan));
+		}
+	}
+
+	/**
+	 * 璁板綍鍒嗙粍瀛楁
+	 *
+	 * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
+	 * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+	 * @param curFieldIndex               褰撳墠瀛楁涓嬫爣
+	 * @param recordFse                   涓氬姟鏁版嵁璁板綍
+	 */
+	private void recordDataAreaGroupField(JSONObject dataAreaGroupFieldRecordObj, List<String> dataAreaGroupFieldNameList, int curFieldIndex, FieldSetEntity recordFse) {
+		String tempFieldName;
+		JSONObject parentObj = dataAreaGroupFieldRecordObj;
+		JSONObject subObj;
+		String value;
+		for (int j = 0; j <= curFieldIndex; j++) {
+			tempFieldName = dataAreaGroupFieldNameList.get(j);
+			value = recordFse.getString(tempFieldName);
+			subObj = parentObj.getJSONObject(value);
+			if (subObj == null) {
+				subObj = new JSONObject();
+				parentObj.put(value, subObj);
+			}
+			parentObj = subObj;
+		}
+	}
+
+	/**
+	 * 鑾峰彇鎸囧畾鐨勪笅绾у垎缁勯」
+	 *
+	 * @param keyObj                      鎸囧畾鐨刱ey
+	 * @param dataAreaGroupFieldNameList  鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+	 * @param dataAreaGroupFieldRecordObj 鏁版嵁鍖哄垎缁勫瓧娈佃褰昽bj
+	 * @return
+	 */
+	private int getAimSubCnt(JSONObject keyObj, List<String> dataAreaGroupFieldNameList, JSONObject dataAreaGroupFieldRecordObj) {
+		String value;
+		JSONObject parentObj = dataAreaGroupFieldRecordObj;
+		JSONObject subObj = null;
+		for (String fieldName : dataAreaGroupFieldNameList) {
+			value = keyObj.getString(fieldName);
+			if (value != null) {
+				subObj = parentObj.getJSONObject(value);
+			} else {
+				break;
+			}
+			parentObj = subObj;
+		}
+		return subObj == null ? 0 : subObj.size();
+	}
 }
diff --git a/src/main/java/com/product/server/report/service/DataListReportService.java b/src/main/java/com/product/server/report/service/DataListReportService.java
index f1ce643..ef59fc0 100644
--- a/src/main/java/com/product/server/report/service/DataListReportService.java
+++ b/src/main/java/com/product/server/report/service/DataListReportService.java
@@ -20,6 +20,8 @@
 import com.product.core.spring.context.SpringMVCContextHolder;
 import com.product.server.report.config.CmnConst;
 import com.product.server.report.config.ReportCode;
+import com.product.server.report.entity.ReportColumn;
+import com.product.server.report.entity.ReportEntity;
 import com.product.util.BaseUtil;
 import com.product.util.SystemParamReplace;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -249,6 +251,180 @@
 		for (Map.Entry<Integer, List<JSONObject>> entry : reportConfigMap.entrySet()) {
 			RedisUtil.setHash(reportConfigUUID, String.valueOf(entry.getKey()), entry.getValue());
 		}
+	}
+
+	/**
+	 * 鑾峰彇鎶ヨ〃
+	 *
+	 * @return
+	 */
+	public ReportEntity getReportEntity(FieldSetEntity fse) {
+		ReportEntity report = null;
+		String reportConfigUUID = fse.getUUID();
+		if (!StringUtils.isEmpty(fse.getString("~report_config_uuid~"))) {
+			reportConfigUUID = fse.getString("~report_config_uuid~");
+		}
+		DataTableEntity reportConfigDte = DataPoolCacheImpl.getInstance().getCacheData(CmnConst.CACHE_REPORT_CONFIG, new String[]{reportConfigUUID});
+		if (BaseUtil.dataTableIsEmpty(reportConfigDte)) {
+			throw new BaseException(ReportCode.GET_CACHE_FIAL.getValue(), ReportCode.GET_CACHE_FIAL.getText() + ":" + CmnConst.CACHE_REPORT_CONFIG);
+		}
+		FieldSetEntity reportConfigFse = reportConfigDte.getFieldSetEntity(0);
+		if (!"1".equals(reportConfigFse.getString(CmnConst.IS_VALID))) {
+			throw new BaseException(ReportCode.INVALID_REPORT.getValue(), ReportCode.INVALID_REPORT.getText());
+		}
+
+		DataTableEntity reportTypeDte = DataPoolCacheImpl.getInstance().getCacheData(CmnConst.CACHE_REPORT_TYPE, new String[]{reportConfigFse.getString(CmnConst.TYPE_UUID)});
+		if (BaseUtil.dataTableIsEmpty(reportTypeDte)) {
+			throw new BaseException(ReportCode.GET_CACHE_FIAL.getValue(), ReportCode.GET_CACHE_FIAL.getText() + ":" + CmnConst.CACHE_REPORT_TYPE);
+		}
+		FieldSetEntity reportTypeFse = reportTypeDte.getFieldSetEntity(0);
+
+		StringBuilder sort = new StringBuilder(128);
+		// 鑾峰彇鎶ヨ〃缂撳瓨淇℃伅
+		Map<Integer, List<JSONObject>> reportConfigMap = getReportConfig(reportConfigUUID, sort);
+		// 鏍规嵁鍏蜂綋鐨刦unction_uuid鍜宐utton_uuid鑾峰彇瀵瑰簲鐨勮矾鐢憋紝鎷煎噾url
+		String url;
+		JSONObject valueObj;
+		for (Map.Entry<Integer, List<JSONObject>> entry : reportConfigMap.entrySet()) {
+			if (entry.getValue() != null) {
+				for (JSONObject tempValueObj : entry.getValue()) {
+					if (entry.getValue() != null) {
+						for (Map.Entry<String, Object> innerEntry : tempValueObj.entrySet()) {
+							if (innerEntry.getValue() instanceof JSONObject) {
+								valueObj = (JSONObject) innerEntry.getValue();
+								if (!StringUtils.isEmpty(valueObj.getString(CmnConst.SUB_REPORT))) {
+									url = valueObj.getString(CmnConst.SUB_REPORT);
+									if (!StringUtils.isEmpty(valueObj.getString(CmnConst.ATTR_URL_PARAM))) {
+										url += "?" + valueObj.getString(CmnConst.ATTR_URL_PARAM);
+									}
+									valueObj.put(CmnConst.ATTR_URL, url);
+									valueObj.put("~isSubReport~", true);
+								} else {
+									if (!StringUtils.isEmpty(valueObj.getString(CmnConst.FUNCTION_UUID)) && !StringUtils.isEmpty(valueObj.getString(CmnConst.BUTTON_UUID))) {
+										url = routerService.functionSkipByButtonUuid(valueObj.getString(CmnConst.FUNCTION_UUID), valueObj.getString(CmnConst.BUTTON_UUID));
+										if (StringUtils.isEmpty(url)) {
+											valueObj.remove(CmnConst.ATTR_URL);
+										} else {
+											if (!StringUtils.isEmpty(valueObj.getString(CmnConst.ATTR_URL_PARAM))) {
+												url += "?" + valueObj.getString(CmnConst.ATTR_URL_PARAM);
+											}
+											valueObj.put(CmnConst.ATTR_URL, url);
+										}
+									} else {
+										valueObj.remove(CmnConst.ATTR_URL);
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		// 鑾峰彇鎶ヨ〃绫诲瀷
+		String reportType = reportTypeFse.getString(CmnConst.TYPE_NAME);
+		// 鑾峰彇鏁版嵁婧�
+		DataTableEntity reportSourceDte = DataPoolCacheImpl.getInstance().getCacheData(CmnConst.CACHE_REPORT_DATASOURCE_CONFIG, new String[]{reportConfigFse.getString(CmnConst.DATASOURCE_UUID)});
+		if (BaseUtil.dataTableIsEmpty(reportSourceDte)) {
+			throw new BaseException(ReportCode.GET_REPORT_DATASOURCE_FIAL.getValue(), ReportCode.GET_REPORT_DATASOURCE_FIAL.getText());
+		}
+		FieldSetEntity reportSourceFse = reportSourceDte.getFieldSetEntity(0);
+		int curPage = fse.getInteger(CmnConst.CPAGE) == null ? 1 : fse.getInteger(CmnConst.CPAGE);
+
+		JSONObject resultObj = new JSONObject();
+		// 棣栨鍔犺浇锛岄粯璁ゆ坊鍔犳潯浠�
+		Map<String, Map<String, String>> outerMap = Maps.newHashMap();
+		if (fse.getBoolean(CmnConst.FIRST_LOAD)) {
+			DataTableEntity allFilterDte = getDefaultSearchFilter(reportSourceFse.getUUID());
+			Map<String, DataTableEntity> subMap = Maps.newHashMap();
+			if (!DataTableEntity.isEmpty(allFilterDte)) {
+				subMap.put("systemFieldMeta", allFilterDte);
+			}
+			DataTableEntity defaultFilterDte = new DataTableEntity();
+
+			FieldSetEntity tempFse;
+
+			Map<String, String> innerMap;
+			for (int i = 0; i < allFilterDte.getRows(); i++) {
+				tempFse = allFilterDte.getFieldSetEntity(i);
+				if (StringUtils.isEmpty(tempFse.getString(CmnConst.LOGICAL_VALUE))) {
+					continue;
+				}
+				defaultFilterDte.addFieldSetEntity(tempFse);
+				innerMap = Maps.newHashMap();
+				innerMap.put(CmnConst.LOGICAL_OPERATOR, tempFse.getString(CmnConst.LOGICAL_OPERATOR));
+				innerMap.put(CmnConst.LOGICAL_VALUE, tempFse.getString(CmnConst.LOGICAL_VALUE));
+				innerMap.put(CmnConst.FIELD_TYPE, tempFse.getString(CmnConst.FIELD_TYPE));
+				outerMap.put(tempFse.getString(CmnConst.FIELD_NAME), innerMap);
+			}
+//			resultObj.put("filterInfo", outerMap);
+
+			if (!DataTableEntity.isEmpty(defaultFilterDte)) {
+				subMap.put("systemSeniorQueryString", defaultFilterDte);
+			}
+			fse.setSubData(subMap);
+		}
+
+		DataTableEntity recordDte = getRecordDte(sort, curPage, reportSourceFse, fse, reportConfigFse, null);
+		// 鏄惁娣诲姞鎬诲悎璁�
+		boolean totalStatisticsFlag = "1".equalsIgnoreCase(reportConfigFse.getString(CmnConst.LAST_TOTAL));
+		String totalName = totalStatisticsFlag ? (StringUtils.isEmpty(reportConfigFse.getString(CmnConst.TOTAL_NAME)) ? "鎬昏" : reportConfigFse.getString(CmnConst.TOTAL_NAME)) : "";
+
+//        JSONObject checkObj = checkRecordDte(recordDte);
+//        if (CmnConst.FALSE.equals(checkObj.getString(CmnConst.RETURN_ATTR_RESULT))) {
+//            return checkObj;
+//        }
+
+//		StringBuilder tableStyle = new StringBuilder(32);
+//		String widthType = reportConfigFse.getString(CmnConst.REPORT_WIDTH_TYPE);
+//		String width = reportConfigFse.getString(CmnConst.REPORT_WIDTH_VALUE);
+//		if (!StringUtils.isEmpty(width)) {
+//			if ("1".equals(widthType)) {
+//				tableStyle.append(" style=\"width:").append(width).append("%\"");
+//			} else if ("0".equals(widthType)) {
+//				tableStyle.append(" style=\"width:").append(width).append("px\"");
+//			}
+//		}
+
+		if (CmnConst.REPORT_TYPE_COMMON.equals(reportType)) {
+			report = commonReportService.getReportEntity(recordDte, totalName, reportConfigMap);
+			//TODO
+			report.setFilterInfo(outerMap);
+		} else if (CmnConst.REPORT_TYPE_GROUP.equals(reportType)) {
+			// 鐗规畩澶勭悊棰濆鏌ヨ鍐呭
+			recordDte.addFieldSetEntity(getRecordDte(sort, curPage, reportSourceFse, fse, reportConfigFse, reportConfigMap));
+//			resultObj.putAll(groupReportService.getReport(recordDte, totalName, reportConfigMap, tableStyle));
+		}
+		//TODO
+
+//		report.setFilterInfo(outerMap);
+		if (CmnConst.FALSE.equals(resultObj.getString(CmnConst.RETURN_ATTR_RESULT))) {
+			resultObj.put(CmnConst.RETURN_ATTR_RESULT, true);
+			resultObj.put(CmnConst.RETURN_ATTR_MESSAGE, "鑾峰彇鎶ヨ〃澶辫触锛�");
+		} else {
+			// 鍒嗛〉鍙傛暟
+			SQLEntity sqlEntity = recordDte.getSqle();
+			if ("1".equals(reportConfigFse.getString(CmnConst.IS_PAGE)) && sqlEntity != null) {
+				report.setPage(true);
+				report.setTotalPage(sqlEntity.getTotalpage());
+				report.setPageSize(StringUtils.isEmpty(reportConfigFse.getString(CmnConst.PAGE_SIZE)) ? 0 : reportConfigFse.getInteger(CmnConst.PAGE_SIZE));
+				report.setPageIndex(curPage);
+//				resultObj.put(CmnConst.IS_PAGE, 1);
+//				resultObj.put(CmnConst.CPAGE, curPage);
+//				resultObj.put("totalCount", sqlEntity.getTotalCount());
+//				resultObj.put("totalpage", sqlEntity.getTotalpage());
+//				resultObj.put("pagesize", StringUtils.isEmpty(reportConfigFse.getString(CmnConst.PAGE_SIZE)) ? 0 : reportConfigFse.getInteger(CmnConst.PAGE_SIZE));
+			}
+		}
+//		if (!DataTableEntity.isEmpty(recordDte)) {
+//			resultObj.put("current_page_count", recordDte.getRows());
+//		}
+		report.setSystemFieldMeta(getSearchInfo(reportSourceFse.getUUID()));
+		report.setReportType(reportConfigFse.getString("type_uuid"));
+//		resultObj.put("systemFieldMeta", );
+		resultObj.put("report_type", reportConfigFse.getString("type_uuid"));
+//        System.out.println(resultObj.getString("html"));
+
+		return report;
 	}
 
 	/**
@@ -1017,6 +1193,74 @@
 	}
 
 	/**
+	 * 鎶ヨ〃-瑙f瀽-鑾峰彇澶撮儴鎴栬�呭熬閮ㄦ爣棰楬tml
+	 *
+	 * @param list                    鎶ヨ〃閰嶇疆淇℃伅锛岀紦瀛榣ist
+	 * @param totalColCount           鎬诲垪鏁�
+	 * @param headAndTailTitleDataMap 澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁map
+	 * @param locationType            浣嶇疆绫诲瀷锛宧ead-澶撮儴锛宼ail-灏鹃儴
+	 * @return
+	 */
+	public List<List<ReportColumn>> getTitle(List<JSONObject> list, int totalColCount, Map<String, Set<String>> headAndTailTitleDataMap, String locationType) {
+		List<List<ReportColumn>> row = new ArrayList<>();
+		StringBuilder html = new StringBuilder(1024);
+		int colspan;
+		int preRow = 0;
+		int preCol = 0;
+		int curRow;
+		int curCol;
+		String value;
+		String style;
+
+		List<ReportColumn> reportColumns = new ArrayList<>();
+		for (JSONObject singleObj : list) {
+			curRow = singleObj.getIntValue(CmnConst.ATTR_Y);
+			curCol = singleObj.getIntValue(CmnConst.ATTR_X);
+			colspan = singleObj.getIntValue(CmnConst.ATTR_COLSPAN);
+			colspan = colspan < 0 ? totalColCount : Math.max(1, colspan);
+			value = replaceFormDataAndSysData(singleObj.getString(CmnConst.ATTR_SHOW_NAME), headAndTailTitleDataMap, singleObj);
+			value = value == null ? "" : value;
+			if ("1".equals(singleObj.getString(CmnConst.ATTR_IS_TITLE))) {
+				style = " class=\"" + CmnConst.CLASS_TR_REPORT_TITLE + "\"";
+			} else {
+				if ("head".equals(locationType)) {
+					style = " class=\"" + CmnConst.CLASS_TR_HEAD + "\"";
+				} else {
+					style = " class=\"" + CmnConst.CLASS_TR_TAIL + "\"";
+				}
+			}
+			if (preRow < curRow) {
+				if (preRow != 0) {
+					row.add(getAimNumTdPlaceholderColumn(totalColCount - preCol, 1));
+				}
+				if (preRow == 0 && preCol == 0 && preCol < curCol - 1) {
+					row.add(getAimNumTdPlaceholderColumn(curCol - preCol - 1, 1));
+				}
+				preCol = curCol;
+			}
+			if (preCol < curCol - 1) {
+				row.add(getAimNumTdPlaceholderColumn(curCol - preCol - 1, 1));
+			}
+			if ("1".equals(singleObj.getString(CmnConst.ATTR_IS_TITLE))) {
+				colspan = totalColCount;
+			}
+			ReportColumn column = new ReportColumn();
+			column.setColspan(colspan);
+			column.setContent(value);
+			reportColumns.add(column);
+			preRow = curRow;
+			preCol = curCol + singleObj.getIntValue(CmnConst.ATTR_COLSPAN) - 1;
+			if ("1".equals(singleObj.getString(CmnConst.ATTR_IS_TITLE))) {
+				preCol = totalColCount;
+			}
+		}
+		row.add(reportColumns);
+		reportColumns.addAll(getAimNumTdPlaceholderColumn(totalColCount - preCol, 1));
+//		row.add();
+		return row;
+	}
+
+	/**
 	 * 鑾峰彇鎸囧畾鏁版嵁闆嗕腑鍖呭惈鐨勬暟鎹尯瀛楁闆嗗悎
 	 *
 	 * @param list 鎸囧畾鏁版嵁闆嗗悎
@@ -1500,6 +1744,30 @@
 	 * @param num
 	 * @return
 	 */
+	public List<ReportColumn> getAimNumTdPlaceholderColumn(int num, int type) {
+		List<ReportColumn> columns = new ArrayList<>();
+		if (num <= 0) {
+			return columns;
+		}
+		if (type == 0) {
+			for (int i = 0; i < num; i++) {
+				columns.add(new ReportColumn());
+			}
+		} else {
+
+			ReportColumn column = new ReportColumn();
+			column.setColspan(num);
+			columns.add(column);
+		}
+		return columns;
+	}
+
+	/**
+	 * 鑾峰彇鎸囧畾涓暟鐨則d鍗犱綅
+	 *
+	 * @param num
+	 * @return
+	 */
 	public String getAimNumTdPlaceholder(int num, int type) {
 		StringBuilder result = new StringBuilder(64);
 		if (num <= 0) {
diff --git a/src/main/java/com/product/server/report/service/GroupReportService.java b/src/main/java/com/product/server/report/service/GroupReportService.java
index 93b677d..59fa0b1 100644
--- a/src/main/java/com/product/server/report/service/GroupReportService.java
+++ b/src/main/java/com/product/server/report/service/GroupReportService.java
@@ -10,6 +10,7 @@
 import com.product.core.service.support.AbstractBaseService;
 import com.product.core.spring.context.SpringMVCContextHolder;
 import com.product.server.report.config.CmnConst;
+import com.product.server.report.entity.ReportColumn;
 import com.product.util.BaseUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -25,993 +26,1374 @@
  */
 @Component
 public class GroupReportService extends AbstractBaseService {
-    @Autowired
-    private DataListReportService dataListReportService;
+	@Autowired
+	private DataListReportService dataListReportService;
 
-    /**
-     * 鎶ヨ〃-瑙f瀽
-     * @param recordDte             涓氬姟鏁版嵁dte
-     * @param totalName             鎬昏鍚嶇О
-     * @param reportConfigMap       鎶ヨ〃閰嶇疆缂撳瓨map
-     * @param tableStyle
-     * @return                      鑾峰彇鍒嗙粍鎶ヨ〃鐨勮鎯�
-     */
-    public JSONObject getReport(DataTableEntity recordDte, String totalName, Map<Integer, List<JSONObject>> reportConfigMap, StringBuilder tableStyle) {
-        StringBuilder reportHtml = new StringBuilder(4096);
+	/**
+	 * 鎶ヨ〃-瑙f瀽
+	 *
+	 * @param recordDte       涓氬姟鏁版嵁dte
+	 * @param totalName       鎬昏鍚嶇О
+	 * @param reportConfigMap 鎶ヨ〃閰嶇疆缂撳瓨map
+	 * @param tableStyle
+	 * @return 鑾峰彇鍒嗙粍鎶ヨ〃鐨勮鎯�
+	 */
+	public JSONObject getReportEntity(DataTableEntity recordDte, String totalName, Map<Integer, List<JSONObject>> reportConfigMap, StringBuilder tableStyle) {
+		StringBuilder reportHtml = new StringBuilder(4096);
 
-        // css
-        StringBuilder cssHtml = dataListReportService.getCssHtml();
+		// css
+//        StringBuilder cssHtml = dataListReportService.getCssHtml();
 
-        // 鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖�
-        StringBuilder groupAndDataAreaHtml = new StringBuilder(1024);
-        Map<String, Set<String>> headAndTailTitleDataMap = Maps.newHashMap();
-        int totalColCount = reportConfigMap.get(0).size();
-        int dataAreaColCount = getGroupAndDataAreaHtmlAndReturnDataAreaColCount(groupAndDataAreaHtml, reportConfigMap, headAndTailTitleDataMap, recordDte, totalName);
-        totalColCount = Math.max(totalColCount, dataAreaColCount);
+		// 鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖�
+		StringBuilder groupAndDataAreaHtml = new StringBuilder(1024);
+		Map<String, Set<String>> headAndTailTitleDataMap = Maps.newHashMap();
+		int totalColCount = reportConfigMap.get(0).size();
+		int dataAreaColCount = getGroupAndDataAreaHtmlAndReturnDataAreaColCount(groupAndDataAreaHtml, reportConfigMap, headAndTailTitleDataMap, recordDte, totalName);
+		totalColCount = Math.max(totalColCount, dataAreaColCount);
 
-        // 澶撮儴鏍囬鍖�
-        StringBuilder headTitleHtml = null;
-        if (!reportConfigMap.get(1).isEmpty()) {
-            headTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(1), totalColCount, headAndTailTitleDataMap, "head");
-        }
+		// 澶撮儴鏍囬鍖�
+		StringBuilder headTitleHtml = null;
+		if (!reportConfigMap.get(1).isEmpty()) {
+			headTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(1), totalColCount, headAndTailTitleDataMap, "head");
+		}
 
-        // 搴曢儴鏍囬鍖�
-        StringBuilder tailTitleHtml = null;
-        if (!reportConfigMap.get(3).isEmpty()) {
-            tailTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(3), totalColCount, headAndTailTitleDataMap, "tail");
-        }
+		// 搴曢儴鏍囬鍖�
+		StringBuilder tailTitleHtml = null;
+		if (!reportConfigMap.get(3).isEmpty()) {
+			tailTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(3), totalColCount, headAndTailTitleDataMap, "tail");
+		}
 
-        reportHtml.append("\n<body>\n<table").append(tableStyle).append(">")
-                .append(cssHtml)
-                .append(headTitleHtml == null ? "" : headTitleHtml)
-                .append(groupAndDataAreaHtml)
-                .append(tailTitleHtml == null ? "" : tailTitleHtml)
-                .append("\n</table>\n</body>");
+//        reportHtml.append("\n<body>\n<table").append(tableStyle).append(">")
+//                .append(cssHtml)
+//                .append(headTitleHtml == null ? "" : headTitleHtml)
+//                .append(groupAndDataAreaHtml)
+//                .append(tailTitleHtml == null ? "" : tailTitleHtml)
+//                .append("\n</table>\n</body>");
 
-        JSONObject resultObj = new JSONObject();
-        resultObj.put(CmnConst.RETURN_ATTR_RESULT, true);
-        resultObj.put(CmnConst.RETURN_ATTR_MESSAGE, "鑾峰彇鎶ヨ〃鎴愬姛锛�");
-        resultObj.put(CmnConst.RETURN_ATTR_HTML, reportHtml);
-        return resultObj;
-    }
+		JSONObject resultObj = new JSONObject();
+		resultObj.put(CmnConst.RETURN_ATTR_RESULT, true);
+		resultObj.put(CmnConst.RETURN_ATTR_MESSAGE, "鑾峰彇鎶ヨ〃鎴愬姛锛�");
+		resultObj.put(CmnConst.RETURN_ATTR_HTML, reportHtml);
+		return resultObj;
+	}
 
-    /**
-     * 鎶ヨ〃-瑙f瀽-鏀惧叆鍒嗙粍琛ㄥご鍖哄拰鏁版嵁Html锛岃繑鍥炲垪鏁�
-     * @param groupAndDataAreaHtml          html瀹瑰櫒
-     * @param reportConfigMap               鎶ヨ〃缂撳瓨鏁版嵁map
-     * @param headAndTailTitleDataMap       澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁map瀹瑰櫒
-     * @param recordDte                     鏁版嵁婧愰泦鍚�
-     * @param totalName                     鎬昏鍚嶇О
-     * @return                              鏁版嵁鍖烘�诲垪鏁�
-     */
-    private int getGroupAndDataAreaHtmlAndReturnDataAreaColCount(StringBuilder groupAndDataAreaHtml, Map<Integer, List<JSONObject>> reportConfigMap, Map<String, Set<String>> headAndTailTitleDataMap, DataTableEntity recordDte, String totalName) {
-        // 鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
-        Map<String, JSONObject> groupAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(2));
-        // 鏁版嵁鍖哄瓧娈电紦瀛榤ap
-        Map<String, JSONObject> dataAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(0));
+	/**
+	 * 鎶ヨ〃-瑙f瀽
+	 *
+	 * @param recordDte       涓氬姟鏁版嵁dte
+	 * @param totalName       鎬昏鍚嶇О
+	 * @param reportConfigMap 鎶ヨ〃閰嶇疆缂撳瓨map
+	 * @param tableStyle
+	 * @return 鑾峰彇鍒嗙粍鎶ヨ〃鐨勮鎯�
+	 */
+	public JSONObject getReport(DataTableEntity recordDte, String totalName, Map<Integer, List<JSONObject>> reportConfigMap, StringBuilder tableStyle) {
+		StringBuilder reportHtml = new StringBuilder(4096);
 
-        // 鍒嗙粍琛ㄥご鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
-        List<String> groupAreaGroupStatisticsFieldNameList = Lists.newArrayList();
-        // 鍒嗙粍琛ㄥご鍖哄垎缁勫瓧娈靛悕绉發ist
-        List<String> groupAreaGroupFieldNameList = Lists.newArrayList();
-        // 鍒嗙粍琛ㄥご鍖哄尯鍩熻寖鍥磑bj
-        JSONObject groupAreaRangeObj = new JSONObject();
-        groupAreaFieldConfigMap.forEach((fieldName, fieldConfigObj) -> {
-            groupAreaGroupFieldNameList.add(fieldName);
-            if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
-                groupAreaGroupStatisticsFieldNameList.add(fieldName);
-            }
-            if (groupAreaRangeObj.getIntValue(CmnConst.MIN_X) == 0) {
-                groupAreaRangeObj.put(CmnConst.MIN_X, fieldConfigObj.getIntValue(CmnConst.ATTR_X));
-            } else {
-                groupAreaRangeObj.put(CmnConst.MIN_X, Math.min(groupAreaRangeObj.getIntValue(CmnConst.MIN_X), fieldConfigObj.getIntValue(CmnConst.ATTR_X)));
-            }
-            groupAreaRangeObj.put(CmnConst.MAX_X, Math.max(groupAreaRangeObj.getIntValue(CmnConst.MAX_X), fieldConfigObj.getIntValue(CmnConst.ATTR_X) + Math.max(1, fieldConfigObj.getIntValue(CmnConst.ATTR_COLSPAN)) - 1));
-            groupAreaRangeObj.put(CmnConst.MAX_Y, Math.max(groupAreaRangeObj.getIntValue(CmnConst.MAX_Y), fieldConfigObj.getIntValue(CmnConst.ATTR_Y) + Math.max(1, fieldConfigObj.getIntValue(CmnConst.ATTR_ROWSPAN)) - 1));
-        });
+		// css
+		StringBuilder cssHtml = dataListReportService.getCssHtml();
 
-        // 鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
-        List<String> dataAreaGroupStatisticsFieldNameList = Lists.newArrayList();
-        // 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
-        List<String> dataAreaGroupFieldNameList = Lists.newArrayList();
-        // 鏁版嵁鍖虹壒娈婄粺璁″瓧娈靛悕绉發ist-鍒嗙粍琛ㄥご鍖轰笅缁熻瀛楁
-        List<String> dataAreaSpStatisticsFieldNameList = Lists.newArrayList();
-        // 鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist-闈炴暟鎹尯鍒嗙粍瀛楁锛岄潪鍒嗙粍琛ㄥご鍖轰笅缁熻瀛楁
-        List<String> dataAreaCommonStatisticsFieldNameList = Lists.newArrayList();
-        dataAreaFieldConfigMap.forEach((fieldName, fieldConfigObj) -> {
-            if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
-                dataAreaGroupFieldNameList.add(fieldName);
-                if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
-                    dataAreaGroupStatisticsFieldNameList.add(fieldName);
-                }
-            } else {
-                if (fieldConfigObj.getIntValue(CmnConst.ATTR_X) < groupAreaRangeObj.getIntValue(CmnConst.MIN_X) || fieldConfigObj.getIntValue(CmnConst.ATTR_X) > groupAreaRangeObj.getIntValue(CmnConst.MAX_X)) {
-                    dataAreaCommonStatisticsFieldNameList.add(fieldName);
-                } else {
-                    dataAreaSpStatisticsFieldNameList.add(fieldName);
-                }
-            }
-        });
+		// 鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖�
+		StringBuilder groupAndDataAreaHtml = new StringBuilder(1024);
+		Map<String, Set<String>> headAndTailTitleDataMap = Maps.newHashMap();
+		int totalColCount = reportConfigMap.get(0).size();
+		int dataAreaColCount = getGroupAndDataAreaHtmlAndReturnDataAreaColCount(groupAndDataAreaHtml, reportConfigMap, headAndTailTitleDataMap, recordDte, totalName);
+		totalColCount = Math.max(totalColCount, dataAreaColCount);
 
-        // 鑾峰彇鍒嗙粍琛ㄥご缁熻瀛楁瀵瑰簲鐨勬暟鎹尯瀛楁map
-        Map<String, List<String>> groupAreaStatisticsField2DataAreaFieldMap = getGroupAreaStatisticsField2DataAreaFieldMap(groupAreaFieldConfigMap, dataAreaFieldConfigMap);
-        // 鑾峰彇鍒嗙粍琛ㄥご鍖烘湯琛屽垎缁勫瓧娈靛搴旀暟鎹尯瀛楁map
-        Map<String, List<String>> groupAreaLastStageField2DataAreaFieldMap = getGroupAreaLastStageField2DataAreaFieldMap(groupAreaFieldConfigMap, dataAreaFieldConfigMap, groupAreaRangeObj);
+		// 澶撮儴鏍囬鍖�
+		StringBuilder headTitleHtml = null;
+		if (!reportConfigMap.get(1).isEmpty()) {
+			headTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(1), totalColCount, headAndTailTitleDataMap, "head");
+		}
 
-        // 鑾峰彇鎸囧畾鏁版嵁闆嗕腑鍖呭惈鐨勬暟鎹尯瀛楁闆嗗悎
-        Set<String> headAndTailFieldSet = Sets.newHashSet();
-        headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(1)));
-        headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(3)));
+		// 搴曢儴鏍囬鍖�
+		StringBuilder tailTitleHtml = null;
+		if (!reportConfigMap.get(3).isEmpty()) {
+			tailTitleHtml = dataListReportService.getTitleHtml(reportConfigMap.get(3), totalColCount, headAndTailTitleDataMap, "tail");
+		}
 
-        // 缁熻map
-        Map<JSONObject, JSONObject> statisticsMap = Maps.newLinkedHashMap();
-        // 鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
-        JSONObject groupAreaFieldRecordObj = new JSONObject(Maps.newTreeMap((o1, o2) -> dataListReportService.compare(o1, o2)));
-        // 鏁版嵁鍖哄垎缁勫瓧娈祇bj
-        JSONObject dataAreaFieldRecordObj = new JSONObject(Maps.newLinkedHashMap());
+		reportHtml.append("\n<body>\n<table").append(tableStyle).append(">")
+				.append(cssHtml)
+				.append(headTitleHtml == null ? "" : headTitleHtml)
+				.append(groupAndDataAreaHtml)
+				.append(tailTitleHtml == null ? "" : tailTitleHtml)
+				.append("\n</table>\n</body>");
 
-        FieldSetEntity recordFse;
-        for (int i = 0;i < recordDte.getRows();i++) {
-            recordFse = recordDte.getFieldSetEntity(i);
+		JSONObject resultObj = new JSONObject();
+		resultObj.put(CmnConst.RETURN_ATTR_RESULT, true);
+		resultObj.put(CmnConst.RETURN_ATTR_MESSAGE, "鑾峰彇鎶ヨ〃鎴愬姛锛�");
+		resultObj.put(CmnConst.RETURN_ATTR_HTML, reportHtml);
+		return resultObj;
+	}
 
-            // 鑾峰彇澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁
-            dataListReportService.getHeadAndTailTitleDataMap(headAndTailTitleDataMap, headAndTailFieldSet, recordFse);
+	/**
+	 * 鎶ヨ〃-瑙f瀽-鏀惧叆鍒嗙粍琛ㄥご鍖哄拰鏁版嵁Html锛岃繑鍥炲垪鏁�
+	 *
+	 * @param groupAndDataAreaHtml    html瀹瑰櫒
+	 * @param reportConfigMap         鎶ヨ〃缂撳瓨鏁版嵁map
+	 * @param headAndTailTitleDataMap 澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁map瀹瑰櫒
+	 * @param recordDte               鏁版嵁婧愰泦鍚�
+	 * @param totalName               鎬昏鍚嶇О
+	 * @return 鏁版嵁鍖烘�诲垪鏁�
+	 */
+	private int getGroupAndDataAreaHtmlAndReturnDataAreaColCount(StringBuilder groupAndDataAreaHtml, Map<Integer, List<JSONObject>> reportConfigMap, Map<String, Set<String>> headAndTailTitleDataMap, DataTableEntity recordDte, String totalName) {
+		// 鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
+		Map<String, JSONObject> groupAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(2));
+		// 鏁版嵁鍖哄瓧娈电紦瀛榤ap
+		Map<String, JSONObject> dataAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(0));
 
-            // 鑾峰彇鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
-            getGroupAreaFieldRecordObj(groupAreaFieldRecordObj, groupAreaFieldConfigMap, recordFse, groupAreaStatisticsField2DataAreaFieldMap, groupAreaLastStageField2DataAreaFieldMap);
+		// 鍒嗙粍琛ㄥご鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
+		List<String> groupAreaGroupStatisticsFieldNameList = Lists.newArrayList();
+		// 鍒嗙粍琛ㄥご鍖哄垎缁勫瓧娈靛悕绉發ist
+		List<String> groupAreaGroupFieldNameList = Lists.newArrayList();
+		// 鍒嗙粍琛ㄥご鍖哄尯鍩熻寖鍥磑bj
+		JSONObject groupAreaRangeObj = new JSONObject();
+		groupAreaFieldConfigMap.forEach((fieldName, fieldConfigObj) -> {
+			groupAreaGroupFieldNameList.add(fieldName);
+			if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+				groupAreaGroupStatisticsFieldNameList.add(fieldName);
+			}
+			if (groupAreaRangeObj.getIntValue(CmnConst.MIN_X) == 0) {
+				groupAreaRangeObj.put(CmnConst.MIN_X, fieldConfigObj.getIntValue(CmnConst.ATTR_X));
+			} else {
+				groupAreaRangeObj.put(CmnConst.MIN_X, Math.min(groupAreaRangeObj.getIntValue(CmnConst.MIN_X), fieldConfigObj.getIntValue(CmnConst.ATTR_X)));
+			}
+			groupAreaRangeObj.put(CmnConst.MAX_X, Math.max(groupAreaRangeObj.getIntValue(CmnConst.MAX_X), fieldConfigObj.getIntValue(CmnConst.ATTR_X) + Math.max(1, fieldConfigObj.getIntValue(CmnConst.ATTR_COLSPAN)) - 1));
+			groupAreaRangeObj.put(CmnConst.MAX_Y, Math.max(groupAreaRangeObj.getIntValue(CmnConst.MAX_Y), fieldConfigObj.getIntValue(CmnConst.ATTR_Y) + Math.max(1, fieldConfigObj.getIntValue(CmnConst.ATTR_ROWSPAN)) - 1));
+		});
 
-            // 鑾峰彇鏁版嵁鍖哄垎缁勫瓧娈祇bj
-            getDataAreaGroupFieldRecordObj(dataAreaFieldRecordObj, dataAreaFieldConfigMap, recordFse);
+		// 鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
+		List<String> dataAreaGroupStatisticsFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+		List<String> dataAreaGroupFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖虹壒娈婄粺璁″瓧娈靛悕绉發ist-鍒嗙粍琛ㄥご鍖轰笅缁熻瀛楁
+		List<String> dataAreaSpStatisticsFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist-闈炴暟鎹尯鍒嗙粍瀛楁锛岄潪鍒嗙粍琛ㄥご鍖轰笅缁熻瀛楁
+		List<String> dataAreaCommonStatisticsFieldNameList = Lists.newArrayList();
+		dataAreaFieldConfigMap.forEach((fieldName, fieldConfigObj) -> {
+			if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+				dataAreaGroupFieldNameList.add(fieldName);
+				if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+					dataAreaGroupStatisticsFieldNameList.add(fieldName);
+				}
+			} else {
+				if (fieldConfigObj.getIntValue(CmnConst.ATTR_X) < groupAreaRangeObj.getIntValue(CmnConst.MIN_X) || fieldConfigObj.getIntValue(CmnConst.ATTR_X) > groupAreaRangeObj.getIntValue(CmnConst.MAX_X)) {
+					dataAreaCommonStatisticsFieldNameList.add(fieldName);
+				} else {
+					dataAreaSpStatisticsFieldNameList.add(fieldName);
+				}
+			}
+		});
 
-            // 鑾峰彇鏁版嵁鍖虹壒娈婂瓧娈电殑缁熻
-            statisticsDataAreaSpField(statisticsMap, dataAreaFieldConfigMap, dataAreaSpStatisticsFieldNameList, recordFse);
+		// 鑾峰彇鍒嗙粍琛ㄥご缁熻瀛楁瀵瑰簲鐨勬暟鎹尯瀛楁map
+		Map<String, List<String>> groupAreaStatisticsField2DataAreaFieldMap = getGroupAreaStatisticsField2DataAreaFieldMap(groupAreaFieldConfigMap, dataAreaFieldConfigMap);
+		// 鑾峰彇鍒嗙粍琛ㄥご鍖烘湯琛屽垎缁勫瓧娈靛搴旀暟鎹尯瀛楁map
+		Map<String, List<String>> groupAreaLastStageField2DataAreaFieldMap = getGroupAreaLastStageField2DataAreaFieldMap(groupAreaFieldConfigMap, dataAreaFieldConfigMap, groupAreaRangeObj);
 
-            // 鑾峰彇鏁版嵁鍖烘櫘閫氬瓧娈电殑缁熻
-            statisticsDataAreaCommonField(statisticsMap, dataAreaFieldConfigMap, dataAreaCommonStatisticsFieldNameList, recordFse);
-        }
+		// 鑾峰彇鎸囧畾鏁版嵁闆嗕腑鍖呭惈鐨勬暟鎹尯瀛楁闆嗗悎
+		Set<String> headAndTailFieldSet = Sets.newHashSet();
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(1)));
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(3)));
 
-        // 鑾峰彇鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖烘�诲垪鏁�
-        int totalColCount = getTotalColCount(groupAreaFieldRecordObj, dataAreaGroupFieldNameList.size(), dataAreaCommonStatisticsFieldNameList.size());
+		// 缁熻map
+		Map<JSONObject, JSONObject> statisticsMap = Maps.newLinkedHashMap();
+		// 鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
+		JSONObject groupAreaFieldRecordObj = new JSONObject(Maps.newTreeMap((o1, o2) -> dataListReportService.compare(o1, o2)));
+		// 鏁版嵁鍖哄垎缁勫瓧娈祇bj
+		JSONObject dataAreaFieldRecordObj = new JSONObject(Maps.newLinkedHashMap());
 
-        // 鏁版嵁鏍囬list
-        List<JSONObject> dataTitleList = Lists.newArrayList();
-        // 鑾峰彇鏍囬html
-        groupAndDataAreaHtml.append(getDataAreaTitleHtml(dataTitleList, groupAreaFieldRecordObj, dataAreaFieldConfigMap, groupAreaRangeObj, dataAreaCommonStatisticsFieldNameList));
-        // 鑾峰彇鍐呭html
-        groupAndDataAreaHtml.append(getDataAreaDataHtml(dataTitleList, dataAreaFieldRecordObj, statisticsMap, totalName, dataAreaGroupFieldNameList, dataAreaFieldConfigMap));
+		FieldSetEntity recordFse;
+		for (int i = 0; i < recordDte.getRows(); i++) {
+			recordFse = recordDte.getFieldSetEntity(i);
 
-        return totalColCount;
-    }
+			// 鑾峰彇澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁
+			dataListReportService.getHeadAndTailTitleDataMap(headAndTailTitleDataMap, headAndTailFieldSet, recordFse);
 
-    /**
-     * 鑾峰彇鍒嗙粍琛ㄥご缁熻瀛楁瀵瑰簲鐨勬暟鎹尯瀛楁map
-     * @param groupAreaFieldConfigMap       鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
-     * @param dataAreaFieldConfigMap        鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @return                              鍒嗙粍琛ㄥご缁熻瀛楁瀵瑰簲鐨勬暟鎹尯瀛楁map
-     */
-    private Map<String,List<String>> getGroupAreaStatisticsField2DataAreaFieldMap(Map<String, JSONObject> groupAreaFieldConfigMap, Map<String, JSONObject> dataAreaFieldConfigMap) {
-        Map<String, List<String>> resultMap = Maps.newLinkedHashMap();
-        String groupAreaFieldName;
-        JSONObject groupAreaFieldConfigObj;
-        JSONObject dataAreaFieldConfigObj;
-        for (Map.Entry<String, JSONObject> groupAreaFieldConfigEntry : groupAreaFieldConfigMap.entrySet()) {
-            groupAreaFieldConfigObj = groupAreaFieldConfigEntry.getValue();
-            if (!"1".equals(groupAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
-                continue;
-            }
-            groupAreaFieldName = groupAreaFieldConfigEntry.getKey();
-            for (Map.Entry<String, JSONObject> dataAreaFieldConfigEntry : dataAreaFieldConfigMap.entrySet()) {
-                dataAreaFieldConfigObj = dataAreaFieldConfigEntry.getValue();
-                if (dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD)).contains(groupAreaFieldName)) {
-                    resultMap.computeIfAbsent(groupAreaFieldName, k -> Lists.newArrayList()).add(dataAreaFieldConfigEntry.getKey());
-                }
-            }
-        }
-        return resultMap;
-    }
+			// 鑾峰彇鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
+			getGroupAreaFieldRecordObj(groupAreaFieldRecordObj, groupAreaFieldConfigMap, recordFse, groupAreaStatisticsField2DataAreaFieldMap, groupAreaLastStageField2DataAreaFieldMap);
 
-    /**
-     * 鑾峰彇鍒嗙粍琛ㄥご鍖烘湯琛屽垎缁勫瓧娈靛搴旀暟鎹尯瀛楁map
-     * @param groupAreaFieldConfigMap       鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
-     * @param dataAreaFieldConfigMap        鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param groupAreaRangeObj             鍒嗙粍琛ㄥご鍖鸿寖鍥磑bj
-     * @return                              鍒嗙粍琛ㄥご鍖烘湯琛屽垎缁勫瓧娈靛搴旀暟鎹尯瀛楁map
-     */
-    private Map<String,List<String>> getGroupAreaLastStageField2DataAreaFieldMap(Map<String, JSONObject> groupAreaFieldConfigMap, Map<String, JSONObject> dataAreaFieldConfigMap, JSONObject groupAreaRangeObj) {
-        Map<String, List<String>> resultMap = Maps.newLinkedHashMap();
-        String groupFieldName;
-        JSONObject groupAreaFieldConfigObj;
-        JSONObject dataAreaFieldConfigObj;
-        for (Map.Entry<String, JSONObject> groupAreaFieldConfigEntry : groupAreaFieldConfigMap.entrySet()) {
-            groupAreaFieldConfigObj = groupAreaFieldConfigEntry.getValue();
-            if (groupAreaFieldConfigObj.getIntValue(CmnConst.ATTR_Y) + Math.max(1, groupAreaFieldConfigObj.getIntValue(CmnConst.ATTR_ROWSPAN)) - 1 < groupAreaRangeObj.getIntValue(CmnConst.MAX_Y)) {
-                continue;
-            }
-            groupFieldName = groupAreaFieldConfigEntry.getKey();
-            for (Map.Entry<String, JSONObject> dataAreaFieldConfigEntry : dataAreaFieldConfigMap.entrySet()) {
-                dataAreaFieldConfigObj = dataAreaFieldConfigEntry.getValue();
-                if (dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD)).contains(groupFieldName)) {
-                    resultMap.computeIfAbsent(groupFieldName, k -> Lists.newArrayList()).add(dataAreaFieldConfigEntry.getKey());
-                }
-            }
+			// 鑾峰彇鏁版嵁鍖哄垎缁勫瓧娈祇bj
+			getDataAreaGroupFieldRecordObj(dataAreaFieldRecordObj, dataAreaFieldConfigMap, recordFse);
 
-        }
-        return resultMap;
-    }
+			// 鑾峰彇鏁版嵁鍖虹壒娈婂瓧娈电殑缁熻
+			statisticsDataAreaSpField(statisticsMap, dataAreaFieldConfigMap, dataAreaSpStatisticsFieldNameList, recordFse);
 
-    /**
-     * 鑾峰彇鏍囬-鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
-     * @param groupAreaFieldRecordObj                       鍒嗙粍琛ㄥご鍖哄瓧娈佃褰昽bj
-     * @param groupAreaFieldConfigMap                       鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
-     * @param recordFse                                     涓氬姟鏁版嵁璁板綍
-     * @param groupAreaStatisticsField2DataAreaFieldMap     鍒嗙粍琛ㄥご鍖虹粺璁″瓧娈靛搴旀暟鎹尯瀛楁map
-     * @param groupAreaLastStageField2DataAreaFieldMap      鍒嗙粍琛ㄥご鍖烘湯绾у瓧娈靛搴旀暟鎹尯瀛楁map
-     */
-    private void getGroupAreaFieldRecordObj(JSONObject groupAreaFieldRecordObj, Map<String, JSONObject> groupAreaFieldConfigMap, FieldSetEntity recordFse,
-                                            Map<String, List<String>> groupAreaStatisticsField2DataAreaFieldMap, Map<String, List<String>> groupAreaLastStageField2DataAreaFieldMap) {
-        JSONObject parentObj = groupAreaFieldRecordObj;
-        JSONObject subObj;
-        String value;
-        List<String> list;
-        String groupAreaGroupFieldName;
-        int i = 0;
-        List<String> statisticsFieldList;
-        String realValue;
-        for (Map.Entry<String, JSONObject> entry : groupAreaFieldConfigMap.entrySet()) {
-            list = Lists.newArrayList();
-            list.addAll(dataListReportService.transfer2List(entry.getValue().get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD)));
-            list.add(entry.getKey());
-            for (;i < list.size();i++) {
-                groupAreaGroupFieldName = list.get(i);
-                realValue = dataListReportService.getRealValue(recordFse, groupAreaGroupFieldName);
-                value = recordFse.getString(groupAreaGroupFieldName);
+			// 鑾峰彇鏁版嵁鍖烘櫘閫氬瓧娈电殑缁熻
+			statisticsDataAreaCommonField(statisticsMap, dataAreaFieldConfigMap, dataAreaCommonStatisticsFieldNameList, recordFse);
+		}
 
-                if (parentObj.get(value) == null) {
-                    subObj = new JSONObject(Maps.newTreeMap((o1, o2) -> dataListReportService.compare(o1, o2)));
-                    parentObj.put(value, subObj);
-                    // 娣诲姞鍒嗙粍琛ㄥご鍖哄垎缁勭粺璁″瓧娈靛搴旀暟鎹尯瀛楁
-                    if (groupAreaStatisticsField2DataAreaFieldMap.containsKey(groupAreaGroupFieldName)) {
-                        parentObj.put(value + CmnConst.STATISTICS_NAME, groupAreaStatisticsField2DataAreaFieldMap.get(groupAreaGroupFieldName));
-                        statisticsFieldList = dataListReportService.transfer2List(parentObj.get(CmnConst.ATTR_STATISTICS_FIELD));
-                        if (statisticsFieldList.isEmpty()) {
-                            parentObj.put(CmnConst.ATTR_STATISTICS_FIELD, statisticsFieldList);
-                        }
-                        if (!statisticsFieldList.contains(value + CmnConst.STATISTICS_NAME)) {
-                            statisticsFieldList.add(value + CmnConst.STATISTICS_NAME);
-                        }
-                    }
-                    // 娣诲姞鍒嗙粍琛ㄥご鍖烘湯绾у瓧娈靛搴旀暟鎹尯瀛楁
-                    if (groupAreaLastStageField2DataAreaFieldMap.containsKey(groupAreaGroupFieldName)) {
-                        parentObj.put(value, groupAreaLastStageField2DataAreaFieldMap.get(groupAreaGroupFieldName));
-                    }
-                    // 娣诲姞field_info
-                    if (StringUtils.isEmpty(parentObj.getString(CmnConst.ATTR_FIELD_INFO))) {
-                        parentObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(groupAreaGroupFieldName));
-                    }
-                    if (!StringUtils.isEmpty(realValue)) {
-                        subObj.put(CmnConst.ATTR_REAL_VALUE, realValue);
-                    }
-                } else {
-                    if (!(parentObj.get(value) instanceof JSONObject)) {
-                        continue;
-                    }
-                    subObj = parentObj.getJSONObject(value);
-                }
-                parentObj = subObj;
-            }
-        }
-    }
+		// 鑾峰彇鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖烘�诲垪鏁�
+		int totalColCount = getTotalColCount(groupAreaFieldRecordObj, dataAreaGroupFieldNameList.size(), dataAreaCommonStatisticsFieldNameList.size());
 
-    /**
-     * 鑾峰彇鏁版嵁鍖哄垎缁勫瓧娈祇bj
-     * @param dataAreaFieldRecordObj    鏁版嵁鍖哄瓧娈佃褰昽bj
-     * @param dataAreaFieldConfigMap    鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param recordFse                 涓氬姟鏁版嵁璁板綍
-     */
-    private void getDataAreaGroupFieldRecordObj(JSONObject dataAreaFieldRecordObj, Map<String, JSONObject> dataAreaFieldConfigMap, FieldSetEntity recordFse) {
-        JSONObject parentObj = dataAreaFieldRecordObj;
-        JSONObject subObj;
-        String value;
-        List<String> list;
-        String groupAreaGroupFieldName;
-        int i = 0;
-        String dataAreaFieldName;
-        JSONObject dataAreaFieldConfigObj;
-        List<String> statisticsFieldList;
-        String realValue;
-        for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
-            dataAreaFieldConfigObj = entry.getValue();
-            if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
-                break;
-            }
-            dataAreaFieldName = entry.getKey();
-            realValue = dataListReportService.getRealValue(recordFse, dataAreaFieldName);
-            list = Lists.newArrayList();
-            list.addAll(dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_DATA_AREA_GROUP_FIELD)));
-            list.add(dataAreaFieldName);
-            for (;i < list.size();i++) {
-                groupAreaGroupFieldName = list.get(i);
-                value = recordFse.getString(groupAreaGroupFieldName);
-                subObj = parentObj.getJSONObject(value);
-                if (subObj == null) {
-                    subObj = new JSONObject(Maps.newLinkedHashMap());
-                    parentObj.put(value, subObj);
-                }
-                // 娣诲姞鏁版嵁鍖哄垎缁勭粺璁″瓧娈�
-                if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
-                    parentObj.put(value + CmnConst.STATISTICS_NAME, new JSONObject());
-                    statisticsFieldList = dataListReportService.transfer2List(parentObj.get(CmnConst.ATTR_STATISTICS_FIELD));
-                    if (statisticsFieldList.isEmpty()) {
-                        parentObj.put(CmnConst.ATTR_STATISTICS_FIELD, statisticsFieldList);
-                    }
-                    if (!statisticsFieldList.contains(value + CmnConst.STATISTICS_NAME)) {
-                        statisticsFieldList.add(value + CmnConst.STATISTICS_NAME);
-                    }
-                }
-                // 娣诲姞field_info
-                if (StringUtils.isEmpty(parentObj.getString(CmnConst.ATTR_FIELD_INFO))) {
-                    parentObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(groupAreaGroupFieldName));
-                }
-                if (!StringUtils.isEmpty(realValue)) {
-                    subObj.put(CmnConst.ATTR_REAL_VALUE, realValue);
-                }
-                parentObj = subObj;
-            }
-        }
-    }
+		// 鏁版嵁鏍囬list
+		List<JSONObject> dataTitleList = Lists.newArrayList();
+		// 鑾峰彇鏍囬html
+		groupAndDataAreaHtml.append(getDataAreaTitleHtml(dataTitleList, groupAreaFieldRecordObj, dataAreaFieldConfigMap, groupAreaRangeObj, dataAreaCommonStatisticsFieldNameList));
+		// 鑾峰彇鍐呭html
+		groupAndDataAreaHtml.append(getDataAreaDataHtml(dataTitleList, dataAreaFieldRecordObj, statisticsMap, totalName, dataAreaGroupFieldNameList, dataAreaFieldConfigMap));
 
-    /**
-     * 鑾峰彇鏁版嵁鍖虹壒娈婂瓧娈电殑缁熻
-     * @param statisticsMap                         缁熻map
-     * @param dataAreaFieldConfigMap                鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param dataAreaSpStatisticsFieldNameList     鏁版嵁鍖虹壒娈婄粺璁″瓧娈靛悕绉發ist锛堝垎缁勮〃澶村尯涓嬬粺璁″瓧娈碉級
-     * @param recordFse                             涓氬姟鏁版嵁璁板綍
-     */
-    private void statisticsDataAreaSpField(Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap, List<String> dataAreaSpStatisticsFieldNameList, FieldSetEntity recordFse) {
-        JSONObject dataAreaFieldConfigObj;
-        List<String> groupAreaGroupFieldNameList;
-        List<String> dataAreaGroupFieldNameList;
-        String value;
-        JSONObject keyObj;
-        JSONObject valueObj;
-        JSONObject groupAreaKeyObj;
-        JSONObject dataAreaKeyObj;
-        String statisticsType;
-        for (String dataAreaFieldName : dataAreaSpStatisticsFieldNameList) {
-            keyObj = new JSONObject();
-            groupAreaKeyObj = new JSONObject();
-            keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
-            dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataAreaFieldName);
-            groupAreaGroupFieldNameList = dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD));
-            dataAreaGroupFieldNameList = dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_DATA_AREA_GROUP_FIELD));
-            value = dataListReportService.getValue(dataAreaFieldConfigObj, recordFse, dataAreaFieldName);
-            statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
-            for (String groupAreaGroupFieldName : groupAreaGroupFieldNameList) {
-                dataAreaKeyObj = new JSONObject();
-                for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
-                    keyObj.remove(dataAreaGroupFieldName);
-                }
-                groupAreaKeyObj.put(groupAreaGroupFieldName, recordFse.getString(groupAreaGroupFieldName));
-                dataListReportService.extendJSONObject(keyObj, groupAreaKeyObj, null);
-                valueObj = statisticsMap.get(keyObj);
-                valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, true);
-                statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
-                for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
-                    dataAreaKeyObj.put(dataAreaGroupFieldName, recordFse.getString(dataAreaGroupFieldName));
-                    keyObj = dataListReportService.extendJSONObject(keyObj, dataAreaKeyObj, null);
-                    valueObj = statisticsMap.get(keyObj);
-                    valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, true);
-                    statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
-                }
-            }
-        }
-    }
+		return totalColCount;
+	}
 
-    /**
-     * 鍙栨暟鎹尯鏅�氬瓧娈电殑缁熻
-     * @param statisticsMap                             缁熻map
-     * @param dataAreaFieldConfigMap                    鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param dataAreaCommonStatisticsFieldNameList     鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist
-     * @param recordFse                                 涓氬姟鏁版嵁璁板綍
-     */
-    private void statisticsDataAreaCommonField(Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap, List<String> dataAreaCommonStatisticsFieldNameList, FieldSetEntity recordFse) {
-        JSONObject dataAreaFieldConfigObj;
-        List<String> dataAreaGroupFieldNameList;
-        String value;
-        JSONObject dataAreaKeyObj = new JSONObject();
-        JSONObject keyObj;
-        JSONObject valueObj;
-        String statisticsType;
-        int i;
-        for (String dataAreaFieldName : dataAreaCommonStatisticsFieldNameList) {
-            i = 0;
-            keyObj = new JSONObject();
-            dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataAreaFieldName);
-            dataAreaGroupFieldNameList = dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_DATA_AREA_GROUP_FIELD));
-            statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
-            value = dataListReportService.getValue(dataAreaFieldConfigObj, recordFse, dataAreaFieldName);
-            keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
-            valueObj = statisticsMap.get(keyObj);
-            valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, false);
-            statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
-            for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
-                i++;
-                dataAreaKeyObj.put(dataAreaGroupFieldName, recordFse.getString(dataAreaGroupFieldName));
-                keyObj = dataListReportService.extendJSONObject(keyObj, dataAreaKeyObj, null);
-                valueObj = statisticsMap.get(keyObj);
-                valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, i == dataAreaGroupFieldNameList.size());
-                statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
-            }
-        }
-    }
+	/**
+	 * 鎶ヨ〃-瑙f瀽-鏀惧叆鍒嗙粍琛ㄥご鍖哄拰鏁版嵁锛岃繑鍥炲垪鏁�
+	 *
+	 * @param groupAndDataArea        瀹瑰櫒
+	 * @param reportConfigMap         鎶ヨ〃缂撳瓨鏁版嵁map
+	 * @param headAndTailTitleDataMap 澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁map瀹瑰櫒
+	 * @param recordDte               鏁版嵁婧愰泦鍚�
+	 * @param totalName               鎬昏鍚嶇О
+	 * @return 鏁版嵁鍖烘�诲垪鏁�
+	 */
+	private int getGroupAndDataAreaAndReturnDataAreaColCount(List<List<ReportColumn>> groupAndDataArea, Map<Integer, List<JSONObject>> reportConfigMap, Map<String, Set<String>> headAndTailTitleDataMap, DataTableEntity recordDte, String totalName) {
+		// 鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
+		Map<String, JSONObject> groupAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(2));
+		// 鏁版嵁鍖哄瓧娈电紦瀛榤ap
+		Map<String, JSONObject> dataAreaFieldConfigMap = dataListReportService.groupAndDataJSONObject2Map(reportConfigMap.get(0));
 
-    /**
-     * 鑾峰彇鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖烘�诲垪鏁�
-     * @param groupAreaFieldRecordObj               鍒嗙粍琛ㄥご鍖哄瓧娈佃褰昽bj
-     * @param dataAreaGroupFieldCount               鏁版嵁鍖哄垎缁勫瓧娈典釜鏁�
-     * @param dataAreaCommonStatisticsFieldCount    鏁版嵁鍖烘櫘閫氱粺璁″瓧娈典釜鏁�
-     * @return                                      鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖烘�诲垪鏁�
-     */
-    private int getTotalColCount(JSONObject groupAreaFieldRecordObj, int dataAreaGroupFieldCount, int dataAreaCommonStatisticsFieldCount) {
-        int groupAreaColCount = getGroupAreaColCount(groupAreaFieldRecordObj, 0);
-        return groupAreaColCount + dataAreaGroupFieldCount + dataAreaCommonStatisticsFieldCount;
-    }
+		// 鍒嗙粍琛ㄥご鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
+		List<String> groupAreaGroupStatisticsFieldNameList = Lists.newArrayList();
+		// 鍒嗙粍琛ㄥご鍖哄垎缁勫瓧娈靛悕绉發ist
+		List<String> groupAreaGroupFieldNameList = Lists.newArrayList();
+		// 鍒嗙粍琛ㄥご鍖哄尯鍩熻寖鍥磑bj
+		JSONObject groupAreaRangeObj = new JSONObject();
+		groupAreaFieldConfigMap.forEach((fieldName, fieldConfigObj) -> {
+			groupAreaGroupFieldNameList.add(fieldName);
+			if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+				groupAreaGroupStatisticsFieldNameList.add(fieldName);
+			}
+			if (groupAreaRangeObj.getIntValue(CmnConst.MIN_X) == 0) {
+				groupAreaRangeObj.put(CmnConst.MIN_X, fieldConfigObj.getIntValue(CmnConst.ATTR_X));
+			} else {
+				groupAreaRangeObj.put(CmnConst.MIN_X, Math.min(groupAreaRangeObj.getIntValue(CmnConst.MIN_X), fieldConfigObj.getIntValue(CmnConst.ATTR_X)));
+			}
+			groupAreaRangeObj.put(CmnConst.MAX_X, Math.max(groupAreaRangeObj.getIntValue(CmnConst.MAX_X), fieldConfigObj.getIntValue(CmnConst.ATTR_X) + Math.max(1, fieldConfigObj.getIntValue(CmnConst.ATTR_COLSPAN)) - 1));
+			groupAreaRangeObj.put(CmnConst.MAX_Y, Math.max(groupAreaRangeObj.getIntValue(CmnConst.MAX_Y), fieldConfigObj.getIntValue(CmnConst.ATTR_Y) + Math.max(1, fieldConfigObj.getIntValue(CmnConst.ATTR_ROWSPAN)) - 1));
+		});
 
-    /**
-     * 鑾峰彇鍒嗙粍琛ㄥご鍖烘�诲垪鏁�
-     * @param curOperateObj         褰撳墠鎿嶄綔鐨刼bj
-     * @param groupAreaColCount     鍒嗙粍琛ㄥご鍖哄垪鏁�
-     * @return                      鍒嗙粍琛ㄥご鍖烘�诲垪鏁�
-     */
-    private int getGroupAreaColCount(JSONObject curOperateObj, int groupAreaColCount) {
-        if (curOperateObj == null) {
-            return groupAreaColCount;
-        }
-        String key;
-        Object value;
-        for (Map.Entry<String, Object> entry : curOperateObj.entrySet()) {
-            key = entry.getKey();
-            if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key)) {
-                continue;
-            }
-            value = entry.getValue();
-            if (value == null) {
-                continue;
-            }
-            if (value instanceof List) {
-                groupAreaColCount += ((List) value).size();
-            } else if (value instanceof JSONObject) {
-                groupAreaColCount = getGroupAreaColCount((JSONObject) value, groupAreaColCount);
-            }
-        }
-        return groupAreaColCount;
-    }
+		// 鏁版嵁鍖哄垎缁勭粺璁″瓧娈靛悕绉發ist
+		List<String> dataAreaGroupStatisticsFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+		List<String> dataAreaGroupFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖虹壒娈婄粺璁″瓧娈靛悕绉發ist-鍒嗙粍琛ㄥご鍖轰笅缁熻瀛楁
+		List<String> dataAreaSpStatisticsFieldNameList = Lists.newArrayList();
+		// 鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist-闈炴暟鎹尯鍒嗙粍瀛楁锛岄潪鍒嗙粍琛ㄥご鍖轰笅缁熻瀛楁
+		List<String> dataAreaCommonStatisticsFieldNameList = Lists.newArrayList();
+		dataAreaFieldConfigMap.forEach((fieldName, fieldConfigObj) -> {
+			if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+				dataAreaGroupFieldNameList.add(fieldName);
+				if ("1".equals(fieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+					dataAreaGroupStatisticsFieldNameList.add(fieldName);
+				}
+			} else {
+				if (fieldConfigObj.getIntValue(CmnConst.ATTR_X) < groupAreaRangeObj.getIntValue(CmnConst.MIN_X) || fieldConfigObj.getIntValue(CmnConst.ATTR_X) > groupAreaRangeObj.getIntValue(CmnConst.MAX_X)) {
+					dataAreaCommonStatisticsFieldNameList.add(fieldName);
+				} else {
+					dataAreaSpStatisticsFieldNameList.add(fieldName);
+				}
+			}
+		});
 
-    /**
-     * 鑾峰彇鏍囬html
-     * @param dataTitleList                             鏁版嵁鏍囬list
-     * @param groupAreaFieldRecordObj                   鍒嗙粍琛ㄥご鍖哄瓧娈佃褰昽bj
-     * @param dataAreaFieldConfigMap                    鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param groupAreaRangeObj                         鍒嗙粍琛ㄥご鍘昏寖鍥磑bj
-     * @param dataAreaCommonStatisticsFieldNameList     鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist
-     * @return                                          鏁版嵁鏍囬html
-     */
-    private StringBuilder getDataAreaTitleHtml(List<JSONObject> dataTitleList, JSONObject groupAreaFieldRecordObj, Map<String, JSONObject> dataAreaFieldConfigMap, JSONObject groupAreaRangeObj, List<String> dataAreaCommonStatisticsFieldNameList) {
-        int maxRow = groupAreaRangeObj.getIntValue(CmnConst.MAX_Y);
-        List<List<JSONObject>> groupAreaRangeTitleList = Lists.newArrayList();
-        for (int i = 0;i <= maxRow;i++) {
-            groupAreaRangeTitleList.add(Lists.newArrayList());
-        }
-        getGroupAreaRangeTitleList(dataAreaFieldConfigMap, groupAreaFieldRecordObj, groupAreaRangeTitleList, new JSONObject(), 0, maxRow, null);
-        
-        List<JSONObject> beforeGroupAreaTitleList = Lists.newArrayList();
-        List<JSONObject> afterGroupAreaTitleList = Lists.newArrayList();
+		// 鑾峰彇鍒嗙粍琛ㄥご缁熻瀛楁瀵瑰簲鐨勬暟鎹尯瀛楁map
+		Map<String, List<String>> groupAreaStatisticsField2DataAreaFieldMap = getGroupAreaStatisticsField2DataAreaFieldMap(groupAreaFieldConfigMap, dataAreaFieldConfigMap);
+		// 鑾峰彇鍒嗙粍琛ㄥご鍖烘湯琛屽垎缁勫瓧娈靛搴旀暟鎹尯瀛楁map
+		Map<String, List<String>> groupAreaLastStageField2DataAreaFieldMap = getGroupAreaLastStageField2DataAreaFieldMap(groupAreaFieldConfigMap, dataAreaFieldConfigMap, groupAreaRangeObj);
 
-        String dataAreaFieldName;
-        JSONObject dataAreaFieldConfigObj;
-        JSONObject titleObj;
-        for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
-            dataAreaFieldName = entry.getKey();
-            dataAreaFieldConfigObj = entry.getValue();
-            titleObj = new JSONObject();
+		// 鑾峰彇鎸囧畾鏁版嵁闆嗕腑鍖呭惈鐨勬暟鎹尯瀛楁闆嗗悎
+		Set<String> headAndTailFieldSet = Sets.newHashSet();
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(1)));
+		headAndTailFieldSet.addAll(dataListReportService.getDataFields(reportConfigMap.get(3)));
+
+		// 缁熻map
+		Map<JSONObject, JSONObject> statisticsMap = Maps.newLinkedHashMap();
+		// 鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
+		JSONObject groupAreaFieldRecordObj = new JSONObject(Maps.newTreeMap((o1, o2) -> dataListReportService.compare(o1, o2)));
+		// 鏁版嵁鍖哄垎缁勫瓧娈祇bj
+		JSONObject dataAreaFieldRecordObj = new JSONObject(Maps.newLinkedHashMap());
+
+		FieldSetEntity recordFse;
+		for (int i = 0; i < recordDte.getRows(); i++) {
+			recordFse = recordDte.getFieldSetEntity(i);
+
+			// 鑾峰彇澶撮儴銆佸熬閮ㄦ爣棰樺尯鏁版嵁瀛楁
+			dataListReportService.getHeadAndTailTitleDataMap(headAndTailTitleDataMap, headAndTailFieldSet, recordFse);
+
+			// 鑾峰彇鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
+			getGroupAreaFieldRecordObj(groupAreaFieldRecordObj, groupAreaFieldConfigMap, recordFse, groupAreaStatisticsField2DataAreaFieldMap, groupAreaLastStageField2DataAreaFieldMap);
+
+			// 鑾峰彇鏁版嵁鍖哄垎缁勫瓧娈祇bj
+			getDataAreaGroupFieldRecordObj(dataAreaFieldRecordObj, dataAreaFieldConfigMap, recordFse);
+
+			// 鑾峰彇鏁版嵁鍖虹壒娈婂瓧娈电殑缁熻
+			statisticsDataAreaSpField(statisticsMap, dataAreaFieldConfigMap, dataAreaSpStatisticsFieldNameList, recordFse);
+
+			// 鑾峰彇鏁版嵁鍖烘櫘閫氬瓧娈电殑缁熻
+			statisticsDataAreaCommonField(statisticsMap, dataAreaFieldConfigMap, dataAreaCommonStatisticsFieldNameList, recordFse);
+		}
+
+		// 鑾峰彇鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖烘�诲垪鏁�
+		int totalColCount = getTotalColCount(groupAreaFieldRecordObj, dataAreaGroupFieldNameList.size(), dataAreaCommonStatisticsFieldNameList.size());
+
+		// 鏁版嵁鏍囬list
+		List<JSONObject> dataTitleList = Lists.newArrayList();
+		// 鑾峰彇鏍囬html
+		groupAndDataArea.addAll(getDataAreaTitle(dataTitleList, groupAreaFieldRecordObj, dataAreaFieldConfigMap, groupAreaRangeObj, dataAreaCommonStatisticsFieldNameList));
+		// 鑾峰彇鍐呭html
+//		groupAndDataAreaHtml.append(getDataAreaDataHtml(dataTitleList, dataAreaFieldRecordObj, statisticsMap, totalName, dataAreaGroupFieldNameList, dataAreaFieldConfigMap));
+
+		return totalColCount;
+	}
+
+	/**
+	 * 鑾峰彇鍒嗙粍琛ㄥご缁熻瀛楁瀵瑰簲鐨勬暟鎹尯瀛楁map
+	 *
+	 * @param groupAreaFieldConfigMap 鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
+	 * @param dataAreaFieldConfigMap  鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @return 鍒嗙粍琛ㄥご缁熻瀛楁瀵瑰簲鐨勬暟鎹尯瀛楁map
+	 */
+	private Map<String, List<String>> getGroupAreaStatisticsField2DataAreaFieldMap(Map<String, JSONObject> groupAreaFieldConfigMap, Map<String, JSONObject> dataAreaFieldConfigMap) {
+		Map<String, List<String>> resultMap = Maps.newLinkedHashMap();
+		String groupAreaFieldName;
+		JSONObject groupAreaFieldConfigObj;
+		JSONObject dataAreaFieldConfigObj;
+		for (Map.Entry<String, JSONObject> groupAreaFieldConfigEntry : groupAreaFieldConfigMap.entrySet()) {
+			groupAreaFieldConfigObj = groupAreaFieldConfigEntry.getValue();
+			if (!"1".equals(groupAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+				continue;
+			}
+			groupAreaFieldName = groupAreaFieldConfigEntry.getKey();
+			for (Map.Entry<String, JSONObject> dataAreaFieldConfigEntry : dataAreaFieldConfigMap.entrySet()) {
+				dataAreaFieldConfigObj = dataAreaFieldConfigEntry.getValue();
+				if (dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD)).contains(groupAreaFieldName)) {
+					resultMap.computeIfAbsent(groupAreaFieldName, k -> Lists.newArrayList()).add(dataAreaFieldConfigEntry.getKey());
+				}
+			}
+		}
+		return resultMap;
+	}
+
+	/**
+	 * 鑾峰彇鍒嗙粍琛ㄥご鍖烘湯琛屽垎缁勫瓧娈靛搴旀暟鎹尯瀛楁map
+	 *
+	 * @param groupAreaFieldConfigMap 鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
+	 * @param dataAreaFieldConfigMap  鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param groupAreaRangeObj       鍒嗙粍琛ㄥご鍖鸿寖鍥磑bj
+	 * @return 鍒嗙粍琛ㄥご鍖烘湯琛屽垎缁勫瓧娈靛搴旀暟鎹尯瀛楁map
+	 */
+	private Map<String, List<String>> getGroupAreaLastStageField2DataAreaFieldMap(Map<String, JSONObject> groupAreaFieldConfigMap, Map<String, JSONObject> dataAreaFieldConfigMap, JSONObject groupAreaRangeObj) {
+		Map<String, List<String>> resultMap = Maps.newLinkedHashMap();
+		String groupFieldName;
+		JSONObject groupAreaFieldConfigObj;
+		JSONObject dataAreaFieldConfigObj;
+		for (Map.Entry<String, JSONObject> groupAreaFieldConfigEntry : groupAreaFieldConfigMap.entrySet()) {
+			groupAreaFieldConfigObj = groupAreaFieldConfigEntry.getValue();
+			if (groupAreaFieldConfigObj.getIntValue(CmnConst.ATTR_Y) + Math.max(1, groupAreaFieldConfigObj.getIntValue(CmnConst.ATTR_ROWSPAN)) - 1 < groupAreaRangeObj.getIntValue(CmnConst.MAX_Y)) {
+				continue;
+			}
+			groupFieldName = groupAreaFieldConfigEntry.getKey();
+			for (Map.Entry<String, JSONObject> dataAreaFieldConfigEntry : dataAreaFieldConfigMap.entrySet()) {
+				dataAreaFieldConfigObj = dataAreaFieldConfigEntry.getValue();
+				if (dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD)).contains(groupFieldName)) {
+					resultMap.computeIfAbsent(groupFieldName, k -> Lists.newArrayList()).add(dataAreaFieldConfigEntry.getKey());
+				}
+			}
+
+		}
+		return resultMap;
+	}
+
+	/**
+	 * 鑾峰彇鏍囬-鍒嗙粍琛ㄥご鍖烘暟鎹畂bj
+	 *
+	 * @param groupAreaFieldRecordObj                   鍒嗙粍琛ㄥご鍖哄瓧娈佃褰昽bj
+	 * @param groupAreaFieldConfigMap                   鍒嗙粍琛ㄥご鍖哄瓧娈电紦瀛榤ap
+	 * @param recordFse                                 涓氬姟鏁版嵁璁板綍
+	 * @param groupAreaStatisticsField2DataAreaFieldMap 鍒嗙粍琛ㄥご鍖虹粺璁″瓧娈靛搴旀暟鎹尯瀛楁map
+	 * @param groupAreaLastStageField2DataAreaFieldMap  鍒嗙粍琛ㄥご鍖烘湯绾у瓧娈靛搴旀暟鎹尯瀛楁map
+	 */
+	private void getGroupAreaFieldRecordObj(JSONObject groupAreaFieldRecordObj, Map<String, JSONObject> groupAreaFieldConfigMap, FieldSetEntity recordFse,
+											Map<String, List<String>> groupAreaStatisticsField2DataAreaFieldMap, Map<String, List<String>> groupAreaLastStageField2DataAreaFieldMap) {
+		JSONObject parentObj = groupAreaFieldRecordObj;
+		JSONObject subObj;
+		String value;
+		List<String> list;
+		String groupAreaGroupFieldName;
+		int i = 0;
+		List<String> statisticsFieldList;
+		String realValue;
+		for (Map.Entry<String, JSONObject> entry : groupAreaFieldConfigMap.entrySet()) {
+			list = Lists.newArrayList();
+			list.addAll(dataListReportService.transfer2List(entry.getValue().get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD)));
+			list.add(entry.getKey());
+			for (; i < list.size(); i++) {
+				groupAreaGroupFieldName = list.get(i);
+				realValue = dataListReportService.getRealValue(recordFse, groupAreaGroupFieldName);
+				value = recordFse.getString(groupAreaGroupFieldName);
+
+				if (parentObj.get(value) == null) {
+					subObj = new JSONObject(Maps.newTreeMap((o1, o2) -> dataListReportService.compare(o1, o2)));
+					parentObj.put(value, subObj);
+					// 娣诲姞鍒嗙粍琛ㄥご鍖哄垎缁勭粺璁″瓧娈靛搴旀暟鎹尯瀛楁
+					if (groupAreaStatisticsField2DataAreaFieldMap.containsKey(groupAreaGroupFieldName)) {
+						parentObj.put(value + CmnConst.STATISTICS_NAME, groupAreaStatisticsField2DataAreaFieldMap.get(groupAreaGroupFieldName));
+						statisticsFieldList = dataListReportService.transfer2List(parentObj.get(CmnConst.ATTR_STATISTICS_FIELD));
+						if (statisticsFieldList.isEmpty()) {
+							parentObj.put(CmnConst.ATTR_STATISTICS_FIELD, statisticsFieldList);
+						}
+						if (!statisticsFieldList.contains(value + CmnConst.STATISTICS_NAME)) {
+							statisticsFieldList.add(value + CmnConst.STATISTICS_NAME);
+						}
+					}
+					// 娣诲姞鍒嗙粍琛ㄥご鍖烘湯绾у瓧娈靛搴旀暟鎹尯瀛楁
+					if (groupAreaLastStageField2DataAreaFieldMap.containsKey(groupAreaGroupFieldName)) {
+						parentObj.put(value, groupAreaLastStageField2DataAreaFieldMap.get(groupAreaGroupFieldName));
+					}
+					// 娣诲姞field_info
+					if (StringUtils.isEmpty(parentObj.getString(CmnConst.ATTR_FIELD_INFO))) {
+						parentObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(groupAreaGroupFieldName));
+					}
+					if (!StringUtils.isEmpty(realValue)) {
+						subObj.put(CmnConst.ATTR_REAL_VALUE, realValue);
+					}
+				} else {
+					if (!(parentObj.get(value) instanceof JSONObject)) {
+						continue;
+					}
+					subObj = parentObj.getJSONObject(value);
+				}
+				parentObj = subObj;
+			}
+		}
+	}
+
+	/**
+	 * 鑾峰彇鏁版嵁鍖哄垎缁勫瓧娈祇bj
+	 *
+	 * @param dataAreaFieldRecordObj 鏁版嵁鍖哄瓧娈佃褰昽bj
+	 * @param dataAreaFieldConfigMap 鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param recordFse              涓氬姟鏁版嵁璁板綍
+	 */
+	private void getDataAreaGroupFieldRecordObj(JSONObject dataAreaFieldRecordObj, Map<String, JSONObject> dataAreaFieldConfigMap, FieldSetEntity recordFse) {
+		JSONObject parentObj = dataAreaFieldRecordObj;
+		JSONObject subObj;
+		String value;
+		List<String> list;
+		String groupAreaGroupFieldName;
+		int i = 0;
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		List<String> statisticsFieldList;
+		String realValue;
+		for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+			dataAreaFieldConfigObj = entry.getValue();
+			if (!"1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+				break;
+			}
+			dataAreaFieldName = entry.getKey();
+			realValue = dataListReportService.getRealValue(recordFse, dataAreaFieldName);
+			list = Lists.newArrayList();
+			list.addAll(dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_DATA_AREA_GROUP_FIELD)));
+			list.add(dataAreaFieldName);
+			for (; i < list.size(); i++) {
+				groupAreaGroupFieldName = list.get(i);
+				value = recordFse.getString(groupAreaGroupFieldName);
+				subObj = parentObj.getJSONObject(value);
+				if (subObj == null) {
+					subObj = new JSONObject(Maps.newLinkedHashMap());
+					parentObj.put(value, subObj);
+				}
+				// 娣诲姞鏁版嵁鍖哄垎缁勭粺璁″瓧娈�
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_STATISTICS))) {
+					parentObj.put(value + CmnConst.STATISTICS_NAME, new JSONObject());
+					statisticsFieldList = dataListReportService.transfer2List(parentObj.get(CmnConst.ATTR_STATISTICS_FIELD));
+					if (statisticsFieldList.isEmpty()) {
+						parentObj.put(CmnConst.ATTR_STATISTICS_FIELD, statisticsFieldList);
+					}
+					if (!statisticsFieldList.contains(value + CmnConst.STATISTICS_NAME)) {
+						statisticsFieldList.add(value + CmnConst.STATISTICS_NAME);
+					}
+				}
+				// 娣诲姞field_info
+				if (StringUtils.isEmpty(parentObj.getString(CmnConst.ATTR_FIELD_INFO))) {
+					parentObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(groupAreaGroupFieldName));
+				}
+				if (!StringUtils.isEmpty(realValue)) {
+					subObj.put(CmnConst.ATTR_REAL_VALUE, realValue);
+				}
+				parentObj = subObj;
+			}
+		}
+	}
+
+	/**
+	 * 鑾峰彇鏁版嵁鍖虹壒娈婂瓧娈电殑缁熻
+	 *
+	 * @param statisticsMap                     缁熻map
+	 * @param dataAreaFieldConfigMap            鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param dataAreaSpStatisticsFieldNameList 鏁版嵁鍖虹壒娈婄粺璁″瓧娈靛悕绉發ist锛堝垎缁勮〃澶村尯涓嬬粺璁″瓧娈碉級
+	 * @param recordFse                         涓氬姟鏁版嵁璁板綍
+	 */
+	private void statisticsDataAreaSpField(Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap, List<String> dataAreaSpStatisticsFieldNameList, FieldSetEntity recordFse) {
+		JSONObject dataAreaFieldConfigObj;
+		List<String> groupAreaGroupFieldNameList;
+		List<String> dataAreaGroupFieldNameList;
+		String value;
+		JSONObject keyObj;
+		JSONObject valueObj;
+		JSONObject groupAreaKeyObj;
+		JSONObject dataAreaKeyObj;
+		String statisticsType;
+		for (String dataAreaFieldName : dataAreaSpStatisticsFieldNameList) {
+			keyObj = new JSONObject();
+			groupAreaKeyObj = new JSONObject();
+			keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+			dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataAreaFieldName);
+			groupAreaGroupFieldNameList = dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_GROUP_AREA_GROUP_FIELD));
+			dataAreaGroupFieldNameList = dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_DATA_AREA_GROUP_FIELD));
+			value = dataListReportService.getValue(dataAreaFieldConfigObj, recordFse, dataAreaFieldName);
+			statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+			for (String groupAreaGroupFieldName : groupAreaGroupFieldNameList) {
+				dataAreaKeyObj = new JSONObject();
+				for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
+					keyObj.remove(dataAreaGroupFieldName);
+				}
+				groupAreaKeyObj.put(groupAreaGroupFieldName, recordFse.getString(groupAreaGroupFieldName));
+				dataListReportService.extendJSONObject(keyObj, groupAreaKeyObj, null);
+				valueObj = statisticsMap.get(keyObj);
+				valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, true);
+				statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
+				for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
+					dataAreaKeyObj.put(dataAreaGroupFieldName, recordFse.getString(dataAreaGroupFieldName));
+					keyObj = dataListReportService.extendJSONObject(keyObj, dataAreaKeyObj, null);
+					valueObj = statisticsMap.get(keyObj);
+					valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, true);
+					statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
+				}
+			}
+		}
+	}
+
+	/**
+	 * 鍙栨暟鎹尯鏅�氬瓧娈电殑缁熻
+	 *
+	 * @param statisticsMap                         缁熻map
+	 * @param dataAreaFieldConfigMap                鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param dataAreaCommonStatisticsFieldNameList 鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist
+	 * @param recordFse                             涓氬姟鏁版嵁璁板綍
+	 */
+	private void statisticsDataAreaCommonField(Map<JSONObject, JSONObject> statisticsMap, Map<String, JSONObject> dataAreaFieldConfigMap, List<String> dataAreaCommonStatisticsFieldNameList, FieldSetEntity recordFse) {
+		JSONObject dataAreaFieldConfigObj;
+		List<String> dataAreaGroupFieldNameList;
+		String value;
+		JSONObject dataAreaKeyObj = new JSONObject();
+		JSONObject keyObj;
+		JSONObject valueObj;
+		String statisticsType;
+		int i;
+		for (String dataAreaFieldName : dataAreaCommonStatisticsFieldNameList) {
+			i = 0;
+			keyObj = new JSONObject();
+			dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataAreaFieldName);
+			dataAreaGroupFieldNameList = dataListReportService.transfer2List(dataAreaFieldConfigObj.get(CmnConst.ATTR_DATA_AREA_GROUP_FIELD));
+			statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+			value = dataListReportService.getValue(dataAreaFieldConfigObj, recordFse, dataAreaFieldName);
+			keyObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+			valueObj = statisticsMap.get(keyObj);
+			valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, false);
+			statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
+			for (String dataAreaGroupFieldName : dataAreaGroupFieldNameList) {
+				i++;
+				dataAreaKeyObj.put(dataAreaGroupFieldName, recordFse.getString(dataAreaGroupFieldName));
+				keyObj = dataListReportService.extendJSONObject(keyObj, dataAreaKeyObj, null);
+				valueObj = statisticsMap.get(keyObj);
+				valueObj = dataListReportService.getStatisticsValueObj(valueObj, dataAreaFieldConfigObj, value, statisticsType, i == dataAreaGroupFieldNameList.size());
+				statisticsMap.put((JSONObject) keyObj.clone(), valueObj);
+			}
+		}
+	}
+
+	/**
+	 * 鑾峰彇鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖烘�诲垪鏁�
+	 *
+	 * @param groupAreaFieldRecordObj            鍒嗙粍琛ㄥご鍖哄瓧娈佃褰昽bj
+	 * @param dataAreaGroupFieldCount            鏁版嵁鍖哄垎缁勫瓧娈典釜鏁�
+	 * @param dataAreaCommonStatisticsFieldCount 鏁版嵁鍖烘櫘閫氱粺璁″瓧娈典釜鏁�
+	 * @return 鍒嗙粍琛ㄥご鍖哄拰鏁版嵁鍖烘�诲垪鏁�
+	 */
+	private int getTotalColCount(JSONObject groupAreaFieldRecordObj, int dataAreaGroupFieldCount, int dataAreaCommonStatisticsFieldCount) {
+		int groupAreaColCount = getGroupAreaColCount(groupAreaFieldRecordObj, 0);
+		return groupAreaColCount + dataAreaGroupFieldCount + dataAreaCommonStatisticsFieldCount;
+	}
+
+	/**
+	 * 鑾峰彇鍒嗙粍琛ㄥご鍖烘�诲垪鏁�
+	 *
+	 * @param curOperateObj     褰撳墠鎿嶄綔鐨刼bj
+	 * @param groupAreaColCount 鍒嗙粍琛ㄥご鍖哄垪鏁�
+	 * @return 鍒嗙粍琛ㄥご鍖烘�诲垪鏁�
+	 */
+	private int getGroupAreaColCount(JSONObject curOperateObj, int groupAreaColCount) {
+		if (curOperateObj == null) {
+			return groupAreaColCount;
+		}
+		String key;
+		Object value;
+		for (Map.Entry<String, Object> entry : curOperateObj.entrySet()) {
+			key = entry.getKey();
+			if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key)) {
+				continue;
+			}
+			value = entry.getValue();
+			if (value == null) {
+				continue;
+			}
+			if (value instanceof List) {
+				groupAreaColCount += ((List) value).size();
+			} else if (value instanceof JSONObject) {
+				groupAreaColCount = getGroupAreaColCount((JSONObject) value, groupAreaColCount);
+			}
+		}
+		return groupAreaColCount;
+	}
+
+	/**
+	 * 鑾峰彇鏍囬
+	 *
+	 * @param dataTitleList                         鏁版嵁鏍囬list
+	 * @param groupAreaFieldRecordObj               鍒嗙粍琛ㄥご鍖哄瓧娈佃褰昽bj
+	 * @param dataAreaFieldConfigMap                鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param groupAreaRangeObj                     鍒嗙粍琛ㄥご鍘昏寖鍥磑bj
+	 * @param dataAreaCommonStatisticsFieldNameList 鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist
+	 * @return 鏁版嵁鏍囬html
+	 */
+	private List<List<ReportColumn>> getDataAreaTitle(List<JSONObject> dataTitleList, JSONObject groupAreaFieldRecordObj, Map<String, JSONObject> dataAreaFieldConfigMap, JSONObject groupAreaRangeObj, List<String> dataAreaCommonStatisticsFieldNameList) {
+		int maxRow = groupAreaRangeObj.getIntValue(CmnConst.MAX_Y);
+		List<List<JSONObject>> groupAreaRangeTitleList = Lists.newArrayList();
+		for (int i = 0; i <= maxRow; i++) {
+			groupAreaRangeTitleList.add(Lists.newArrayList());
+		}
+		getGroupAreaRangeTitleList(dataAreaFieldConfigMap, groupAreaFieldRecordObj, groupAreaRangeTitleList, new JSONObject(), 0, maxRow, null);
+
+		List<JSONObject> beforeGroupAreaTitleList = Lists.newArrayList();
+		List<JSONObject> afterGroupAreaTitleList = Lists.newArrayList();
+
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		JSONObject titleObj;
+		for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+			dataAreaFieldName = entry.getKey();
+			dataAreaFieldConfigObj = entry.getValue();
+			titleObj = new JSONObject();
 //            titleObj.put(CmnConst.ATTR_FIELD_INFO, getFieldInfo(dataAreaFieldConfigObj));
-            titleObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
-            if (dataAreaCommonStatisticsFieldNameList.contains(dataAreaFieldName)) {
-                titleObj.put(CmnConst.ATTR_SHOW_NAME, dataListReportService.getStatisticsDesc(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS), dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME)));
-            } else {
-                titleObj.put(CmnConst.ATTR_SHOW_NAME, dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME));
-            }
-            titleObj.put(CmnConst.ATTR_ROWSPAN, maxRow + 1);
-            titleObj.put(CmnConst.ATTR_COLSPAN, 1);
-            if (dataAreaFieldConfigObj.getIntValue(CmnConst.ATTR_X) < groupAreaRangeObj.getIntValue(CmnConst.MIN_X)) {
-                beforeGroupAreaTitleList.add(titleObj);
-            }
-            if (dataAreaFieldConfigObj.getIntValue(CmnConst.ATTR_X) > groupAreaRangeObj.getIntValue(CmnConst.MAX_X)) {
-                if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
-                    beforeGroupAreaTitleList.add(titleObj);
-                } else {
-                    afterGroupAreaTitleList.add(titleObj);
-                }
-            }
-        }
+			titleObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+			if (dataAreaCommonStatisticsFieldNameList.contains(dataAreaFieldName)) {
+				titleObj.put(CmnConst.ATTR_SHOW_NAME, dataListReportService.getStatisticsDesc(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS), dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME)));
+			} else {
+				titleObj.put(CmnConst.ATTR_SHOW_NAME, dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME));
+			}
+			titleObj.put(CmnConst.ATTR_ROWSPAN, maxRow + 1);
+			titleObj.put(CmnConst.ATTR_COLSPAN, 1);
+			if (dataAreaFieldConfigObj.getIntValue(CmnConst.ATTR_X) < groupAreaRangeObj.getIntValue(CmnConst.MIN_X)) {
+				beforeGroupAreaTitleList.add(titleObj);
+			}
+			if (dataAreaFieldConfigObj.getIntValue(CmnConst.ATTR_X) > groupAreaRangeObj.getIntValue(CmnConst.MAX_X)) {
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+					beforeGroupAreaTitleList.add(titleObj);
+				} else {
+					afterGroupAreaTitleList.add(titleObj);
+				}
+			}
+		}
 
-        dataTitleList.addAll(groupAreaRangeTitleList.get(maxRow));
-        dataTitleList.addAll(afterGroupAreaTitleList);
+		dataTitleList.addAll(groupAreaRangeTitleList.get(maxRow));
+		dataTitleList.addAll(afterGroupAreaTitleList);
 
-        List<JSONObject> firstList = Lists.newArrayList();
-        firstList.addAll(beforeGroupAreaTitleList);
-        firstList.addAll(groupAreaRangeTitleList.get(0));
-        firstList.addAll(afterGroupAreaTitleList);
+		List<JSONObject> firstList = Lists.newArrayList();
+		firstList.addAll(beforeGroupAreaTitleList);
+		firstList.addAll(groupAreaRangeTitleList.get(0));
+		firstList.addAll(afterGroupAreaTitleList);
 
-        groupAreaRangeTitleList.set(0, firstList);
+		groupAreaRangeTitleList.set(0, firstList);
 
-        StringBuilder html = new StringBuilder(1024);
-        int rowspan;
-        int colspan;
-        String value;
-        for (List<JSONObject> rowList : groupAreaRangeTitleList) {
-            html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_TITLE).append("\">\n    ");
-            for (JSONObject dataTitleObj : rowList) {
-                rowspan = Math.max(1, dataTitleObj.getIntValue(CmnConst.ATTR_ROWSPAN));
-                colspan = Math.max(1, dataTitleObj.getIntValue(CmnConst.ATTR_COLSPAN));
-                value = dataTitleObj.getString(CmnConst.ATTR_SHOW_NAME);
-                if (!StringUtils.isEmpty(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO))) {
-                    dataAreaFieldName = dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO));
-                    value = dataListReportService.dealTdWidth(dataAreaFieldConfigMap.get(dataAreaFieldName), value);
-                }
-                html.append("<td rowspan=\"").append(rowspan).append("\" colspan=\"").append(colspan).append("\">").append(value == null ? "" : value).append("</td>");
-            }
-            html.append("\n</tr>");
-        }
-        return html;
-    }
+//		StringBuilder html = new StringBuilder(1024);
+		int rowspan;
+		int colspan;
+		String value;
+		List<List<ReportColumn>> rowColumn = new ArrayList<>();
+		for (List<JSONObject> rowList : groupAreaRangeTitleList) {
+			List<ReportColumn> columns = new ArrayList<>();
+//			html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_TITLE).append("\">\n    ");
+			for (JSONObject dataTitleObj : rowList) {
+				rowspan = Math.max(1, dataTitleObj.getIntValue(CmnConst.ATTR_ROWSPAN));
+				colspan = Math.max(1, dataTitleObj.getIntValue(CmnConst.ATTR_COLSPAN));
+				value = dataTitleObj.getString(CmnConst.ATTR_SHOW_NAME);
+				if (!StringUtils.isEmpty(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO))) {
+					dataAreaFieldName = dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO));
+					value = dataListReportService.dealTdWidth(dataAreaFieldConfigMap.get(dataAreaFieldName), value);
+				}
+				ReportColumn column = new ReportColumn();
+				column.setRowspan(rowspan);
+				column.setColspan(colspan);
+				column.setContent(value);
+				columns.add(column);
+//				html.append("<td rowspan=\"").append(rowspan).append("\" colspan=\"").append(colspan).append("\">").append(value == null ? "" : value).append("</td>");
+			}
+			rowColumn.add(columns);
+//			html.append("\n</tr>");
+		}
+		return rowColumn;
+	}
 
-    /**
-     * 鑾峰彇鍒嗙粍琛ㄥご鍖鸿寖鍥寸殑鏍囬list
-     * @param dataAreaFieldConfigMap        鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param curOperateObj                 褰撳墠鎿嶄綔obj
-     * @param groupAreaRangeTitleList       鍒嗙粍琛ㄥご鍖鸿寖鍥翠笅鏁版嵁鏍囬list
-     * @param preTitleObj                   鏈�杩戞搷浣滅殑鏍囬obj
-     * @param row                           褰撳墠琛屾暟
-     * @param maxRow                        鏈�澶ц鏁�
-     */
-    private void getGroupAreaRangeTitleList(Map<String, JSONObject> dataAreaFieldConfigMap, JSONObject curOperateObj, List<List<JSONObject>> groupAreaRangeTitleList, JSONObject preTitleObj, int row, int maxRow, String parentFieldName) {
-        if (curOperateObj == null || curOperateObj.isEmpty()) {
-            return;
-        }
-        String key;
-        Object value;
-        JSONObject curTitleObj;
-        String groupAreaFieldName = dataListReportService.fieldInfo2FieldName(curOperateObj.getString(CmnConst.ATTR_FIELD_INFO));
-        List<String> statisticsFieldList = dataListReportService.transfer2List(curOperateObj.get(CmnConst.ATTR_STATISTICS_FIELD));
-        String realValue = curOperateObj.getString(CmnConst.ATTR_REAL_VALUE);
-        String fieldName = dataListReportService.fieldInfo2FieldName(curOperateObj.getString(CmnConst.ATTR_FIELD_INFO));
-        String newKey;
-        JSONObject realValueObj;
-        for (Map.Entry<String, Object> entry : curOperateObj.entrySet()) {
-            curTitleObj = dataListReportService.extendJSONObject(null, preTitleObj, null);
-            if (!StringUtils.isEmpty(realValue) && !StringUtils.isEmpty(parentFieldName)) {
-                if (curTitleObj.get(CmnConst.ATTR_REAL_VALUE) == null) {
-                    realValueObj = new JSONObject();
-                    curTitleObj.put(CmnConst.ATTR_REAL_VALUE, realValueObj);
-                } else {
-                    realValueObj = (JSONObject) curTitleObj.get(CmnConst.ATTR_REAL_VALUE);
-                }
-                realValueObj.put(parentFieldName, realValue);
-            }
-            key = entry.getKey();
-            if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key) || CmnConst.ATTR_REAL_VALUE.equals(key)) {
-                continue;
-            }
-            value = entry.getValue();
-            if (value == null) {
-                continue;
-            }
-            curTitleObj.put(CmnConst.ATTR_SHOW_NAME, key);
-            if (statisticsFieldList.contains(key)) {
-                curTitleObj.put(CmnConst.ATTR_IS_STATISTICS_FIELD, "1");
-                newKey = key.replace(CmnConst.STATISTICS_NAME, "");
-                curTitleObj.put(groupAreaFieldName, newKey);
-                curTitleObj.put(CmnConst.ATTR_GROUP_AREA_SUB_CNT, getSubCnt(curOperateObj.getJSONObject(newKey)));
-            } else {
-                curTitleObj.put(groupAreaFieldName, key);
-            }
-            groupAreaRangeTitleList.get(row).add(curTitleObj);
-            if (value instanceof List) {
-                curTitleObj.put(CmnConst.ATTR_COLSPAN, ((List) value).size());
-                curTitleObj.put(CmnConst.ATTR_ROWSPAN, maxRow - row);
-                for (String dataAreaFieldName : (List<String>) value) {
-                    JSONObject cloneTitleObj = (JSONObject) curTitleObj.clone();
-                    cloneTitleObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
-                    cloneTitleObj.put(CmnConst.ATTR_COLSPAN, 1);
-                    cloneTitleObj.put(CmnConst.ATTR_ROWSPAN, 1);
-                    JSONObject dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataAreaFieldName);
-                    cloneTitleObj.put(CmnConst.ATTR_SHOW_NAME, dataListReportService.getStatisticsDesc(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS), dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME)));
-                    groupAreaRangeTitleList.get(maxRow).add(cloneTitleObj);
-                }
-            } else {
-                if (value instanceof JSONObject) {
-                    curTitleObj.put(CmnConst.ATTR_COLSPAN, getGroupAreaColCount((JSONObject) value, 0));
-                    curTitleObj.put(CmnConst.ATTR_ROWSPAN, 1);
-                    getGroupAreaRangeTitleList(dataAreaFieldConfigMap, (JSONObject) value, groupAreaRangeTitleList, curTitleObj, row + 1, maxRow, fieldName);
-                }
-            }
-        }
-    }
+	/**
+	 * 鑾峰彇鏍囬html
+	 *
+	 * @param dataTitleList                         鏁版嵁鏍囬list
+	 * @param groupAreaFieldRecordObj               鍒嗙粍琛ㄥご鍖哄瓧娈佃褰昽bj
+	 * @param dataAreaFieldConfigMap                鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param groupAreaRangeObj                     鍒嗙粍琛ㄥご鍘昏寖鍥磑bj
+	 * @param dataAreaCommonStatisticsFieldNameList 鏁版嵁鍖烘櫘閫氱粺璁″瓧娈靛悕绉發ist
+	 * @return 鏁版嵁鏍囬html
+	 */
+	private StringBuilder getDataAreaTitleHtml(List<JSONObject> dataTitleList, JSONObject groupAreaFieldRecordObj, Map<String, JSONObject> dataAreaFieldConfigMap, JSONObject groupAreaRangeObj, List<String> dataAreaCommonStatisticsFieldNameList) {
+		int maxRow = groupAreaRangeObj.getIntValue(CmnConst.MAX_Y);
+		List<List<JSONObject>> groupAreaRangeTitleList = Lists.newArrayList();
+		for (int i = 0; i <= maxRow; i++) {
+			groupAreaRangeTitleList.add(Lists.newArrayList());
+		}
+		getGroupAreaRangeTitleList(dataAreaFieldConfigMap, groupAreaFieldRecordObj, groupAreaRangeTitleList, new JSONObject(), 0, maxRow, null);
 
-    /**
-     * 鑾峰彇涓嬬骇鍒嗙粍椤规暟
-     * @param obj       寰呮搷浣滅殑obj
-     * @return          涓嬬骇鍒嗙粍椤规暟
-     */
-    private int getSubCnt(JSONObject obj) {
-        int count = 0;
-        List<String> statisticsFieldList = dataListReportService.transfer2List(obj.get(CmnConst.ATTR_STATISTICS_FIELD));
-        for (String key : obj.keySet()) {
-            if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key) || statisticsFieldList.contains(key)) {
-                continue;
-            }
-            count++;
-        }
-        return count;
-    }
+		List<JSONObject> beforeGroupAreaTitleList = Lists.newArrayList();
+		List<JSONObject> afterGroupAreaTitleList = Lists.newArrayList();
 
-    /**
-     * 鑾峰彇鍐呭html
-     * @param dataTitleList                 鏁版嵁鏍囬list
-     * @param dataAreaFieldRecordObj        鏁版嵁鍖哄瓧娈佃褰昽bj
-     * @param statisticsMap                 缁熻map
-     * @param totalName                     鎬昏鍚嶇О锛岄潪绌�-闇�瑕佹�昏
-     * @param dataAreaGroupFieldNameList    鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
-     * @param dataAreaFieldConfigMap        鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @return                              涓氬姟鏁版嵁鍐呭html
-     */
-    private StringBuilder getDataAreaDataHtml(List<JSONObject> dataTitleList, JSONObject dataAreaFieldRecordObj, Map<JSONObject, JSONObject> statisticsMap, String totalName, List<String> dataAreaGroupFieldNameList, Map<String, JSONObject> dataAreaFieldConfigMap) {
-        List<List<JSONObject>> dataAreaGroupFieldDataList = Lists.newArrayList();
-        getDataAreaGroupFieldDataList(dataAreaFieldRecordObj, dataAreaGroupFieldDataList, new JSONObject(), 1, 1, dataAreaGroupFieldNameList.size(), null);
+		String dataAreaFieldName;
+		JSONObject dataAreaFieldConfigObj;
+		JSONObject titleObj;
+		for (Map.Entry<String, JSONObject> entry : dataAreaFieldConfigMap.entrySet()) {
+			dataAreaFieldName = entry.getKey();
+			dataAreaFieldConfigObj = entry.getValue();
+			titleObj = new JSONObject();
+//            titleObj.put(CmnConst.ATTR_FIELD_INFO, getFieldInfo(dataAreaFieldConfigObj));
+			titleObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+			if (dataAreaCommonStatisticsFieldNameList.contains(dataAreaFieldName)) {
+				titleObj.put(CmnConst.ATTR_SHOW_NAME, dataListReportService.getStatisticsDesc(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS), dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME)));
+			} else {
+				titleObj.put(CmnConst.ATTR_SHOW_NAME, dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME));
+			}
+			titleObj.put(CmnConst.ATTR_ROWSPAN, maxRow + 1);
+			titleObj.put(CmnConst.ATTR_COLSPAN, 1);
+			if (dataAreaFieldConfigObj.getIntValue(CmnConst.ATTR_X) < groupAreaRangeObj.getIntValue(CmnConst.MIN_X)) {
+				beforeGroupAreaTitleList.add(titleObj);
+			}
+			if (dataAreaFieldConfigObj.getIntValue(CmnConst.ATTR_X) > groupAreaRangeObj.getIntValue(CmnConst.MAX_X)) {
+				if ("1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_GROUP))) {
+					beforeGroupAreaTitleList.add(titleObj);
+				} else {
+					afterGroupAreaTitleList.add(titleObj);
+				}
+			}
+		}
 
-        List<JSONObject> groupTitleList = Lists.newArrayList();
-        JSONObject obj;
-        for (List<JSONObject> rowList : dataAreaGroupFieldDataList) {
-            obj = dataListReportService.extendJSONObject(null, rowList.get(rowList.size() - 1), Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD), -1);
-            groupTitleList.add(obj);
-        }
+		dataTitleList.addAll(groupAreaRangeTitleList.get(maxRow));
+		dataTitleList.addAll(afterGroupAreaTitleList);
 
-        StringBuilder html = new StringBuilder(1024);
-        JSONObject dataAreaGroupFieldObj;
-        int rowspan;
-        int colspan;
-        String value;
-        JSONObject groupTitleObj;
-        JSONObject keyObj;
-        JSONObject valueObj;
-        String statisticsType;
-        JSONObject dataAreaFieldConfigObj;
-        int groupAreaSubCnt;
-        int dataAreaSubCnt;
-        List<JSONObject> curRowList;
-        int index;
-        for (int i = 0;i < dataAreaGroupFieldDataList.size();i++) {
-            index = 0;
-            curRowList = dataAreaGroupFieldDataList.get(i);
-            if (!curRowList.isEmpty()) {
-                for (int j = 0; j < curRowList.size(); j++) {
-                    dataAreaGroupFieldObj = curRowList.get(j);
-                    if (dataAreaGroupFieldObj.isEmpty()) {
-                        continue;
-                    }
-                    if (index == 0) {
-                        if ("1".equals(dataAreaGroupFieldObj.getString(CmnConst.ATTR_IS_STATISTICS_FIELD))) {
-                            html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
-                        } else {
-                            html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
-                        }
-                    }
-                    rowspan = Math.max(1, dataAreaGroupFieldObj.getIntValue(CmnConst.ATTR_ROWSPAN));
-                    colspan = Math.max(1, dataAreaGroupFieldObj.getIntValue(CmnConst.ATTR_COLSPAN));
-                    value = dataAreaGroupFieldObj.getString(CmnConst.ATTR_SHOW_NAME);
-                    html.append("<td rowspan=\"").append(rowspan).append("\" colspan=\"").append(colspan).append("\">").append(value == null ? "" : value).append("</td>");
-                    index++;
-                }
-            } else {
-                html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
-            }
-            groupTitleObj = groupTitleList.get(i);
-            for (JSONObject dataTitleObj : dataTitleList) {
-                keyObj = dataListReportService.extendJSONObject((JSONObject) groupTitleObj.clone(), dataTitleObj, Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD, CmnConst.ATTR_REAL_VALUE), -1);
-                dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO)));
-                if (dataAreaFieldConfigObj != null) {
-                    groupAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
-                    dataAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_DATA_AREA_SUB_CNT);
-                    keyObj.remove(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
-                    keyObj.remove(CmnConst.ATTR_DATA_AREA_SUB_CNT);
-                    keyObj.remove(CmnConst.ATTR_REAL_VALUE);
-                    statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
-                    valueObj = statisticsMap.get(keyObj);
-                    if (valueObj == null || valueObj.isEmpty()) {
-                        value = getFinalValue(keyObj, dataAreaFieldConfigObj, statisticsMap);
-                    } else {
-                        if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
-                            if (dataAreaSubCnt == 0 && groupAreaSubCnt == 0) {
-                                value = valueObj.getString(statisticsType);
-                            } else {
-                                value = getTwoTypesGroupAvgStatisticsValue(dataAreaSubCnt, groupAreaSubCnt, valueObj, dataAreaFieldConfigObj, statisticsType);
-                            }
-                        } else {
-                            value = valueObj.getString(statisticsType);
-                        }
-                        valueObj.put(CmnConst.ATTR_FINAL_VALUE, value);
-                    }
-                } else {
-                    value = "";
-                }
-                html.append("<td");
-                if (!StringUtils.isEmpty(value)) {
-                    // class
-                    if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
-                        dataListReportService.extendJSONObject(keyObj, dataAreaFieldConfigObj, Collections.singletonList(CmnConst.ATTR_URL));
-                        html.append(" class=\"").append(CmnConst.CLASS_TD_CAN_TURN).append("\"");
-                    }
-                    // 瀛楁灞炴��
-                    dataListReportService.getTdAttrObj(keyObj, groupTitleObj);
-                    dataListReportService.getTdAttrObj(keyObj, dataTitleObj);
-                    html.append(dataListReportService.getTdAttrByObj(keyObj));
-                    // 鏍煎紡
-                    value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
-                }
-                html.append(">").append(value == null ? "" : value).append("</td>");
-            }
-            html.append("\n</tr>");
-        }
+		List<JSONObject> firstList = Lists.newArrayList();
+		firstList.addAll(beforeGroupAreaTitleList);
+		firstList.addAll(groupAreaRangeTitleList.get(0));
+		firstList.addAll(afterGroupAreaTitleList);
 
-        // 鎬昏
-        if (!StringUtils.isEmpty(totalName)) {
-            html.append(getTotalStatisticsHtml(statisticsMap, dataTitleList, dataAreaFieldConfigMap, dataAreaGroupFieldNameList.size(), getSubCnt(dataAreaFieldRecordObj), totalName));
-        }
+		groupAreaRangeTitleList.set(0, firstList);
 
-        return html;
-    }
+		StringBuilder html = new StringBuilder(1024);
+		int rowspan;
+		int colspan;
+		String value;
+		for (List<JSONObject> rowList : groupAreaRangeTitleList) {
+			html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_TITLE).append("\">\n    ");
+			for (JSONObject dataTitleObj : rowList) {
+				rowspan = Math.max(1, dataTitleObj.getIntValue(CmnConst.ATTR_ROWSPAN));
+				colspan = Math.max(1, dataTitleObj.getIntValue(CmnConst.ATTR_COLSPAN));
+				value = dataTitleObj.getString(CmnConst.ATTR_SHOW_NAME);
+				if (!StringUtils.isEmpty(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO))) {
+					dataAreaFieldName = dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO));
+					value = dataListReportService.dealTdWidth(dataAreaFieldConfigMap.get(dataAreaFieldName), value);
+				}
+				html.append("<td rowspan=\"").append(rowspan).append("\" colspan=\"").append(colspan).append("\">").append(value == null ? "" : value).append("</td>");
+			}
+			html.append("\n</tr>");
+		}
+		return html;
+	}
 
-    /**
-     * 鑾峰彇鏁版嵁鍖哄垎缁勫瓧娈垫暟鎹甽ist
-     * @param curOperateObj                 褰撳墠鎿嶄綔obj
-     * @param dataAreaGroupFieldDataList    鏁版嵁鍖哄垎缁勫瓧娈垫暟鎹甽ist
-     * @param preObj                        鏈�杩戞搷浣滅殑obj
-     * @param row                           褰撳墠琛屾暟
-     * @param maxCol                        鏈�澶у垪鏁�
-     * @return                              鏁版嵁鍖哄垎缁勫瓧娈垫暟鎹甽ist
-     */
-    private int getDataAreaGroupFieldDataList(JSONObject curOperateObj, List<List<JSONObject>> dataAreaGroupFieldDataList, JSONObject preObj, int row, int col, int maxCol, String parentFieldName) {
-        String key;
-        Object value;
-        JSONObject curObj;
-        JSONObject topLeftCornerObj;
-        String dataAreaFieldName = dataListReportService.fieldInfo2FieldName(curOperateObj.getString(CmnConst.ATTR_FIELD_INFO));
-        List<String> statisticsFieldList = dataListReportService.transfer2List(curOperateObj.get(CmnConst.ATTR_STATISTICS_FIELD));
-        String realValue = curOperateObj.getString(CmnConst.ATTR_REAL_VALUE);
-        JSONObject objValue;
-        String newKey;
-        List<JSONObject> curRowList;
-        JSONObject realValueObj;
-        for (Map.Entry<String, Object> entry : curOperateObj.entrySet()) {
-            curObj = dataListReportService.extendJSONObject(null, preObj, null);
-            key = entry.getKey();
-            if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key) || CmnConst.ATTR_REAL_VALUE.equals(key)) {
-                continue;
-            }
-            value = entry.getValue();
-            if (value == null) {
-                continue;
-            }
-            if (!StringUtils.isEmpty(realValue) && !StringUtils.isEmpty(parentFieldName)) {
-                if (curObj.get(CmnConst.ATTR_REAL_VALUE) == null) {
-                    realValueObj = new JSONObject();
-                    curObj.put(CmnConst.ATTR_REAL_VALUE, realValueObj);
-                } else {
-                    realValueObj = (JSONObject) curObj.get(CmnConst.ATTR_REAL_VALUE);
-                }
-                realValueObj.put(parentFieldName, realValue);
-            }
-            if (dataAreaGroupFieldDataList.size() < row) {
-                curRowList = Lists.newArrayList();
-                dataAreaGroupFieldDataList.add(curRowList);
-            } else {
-                curRowList = dataAreaGroupFieldDataList.get(row - 1);
-            }
-            if (curRowList.size() < col - 1) {
-                for (int i = 0; i < col - 1; i++) {
-                    curRowList.add(new JSONObject());
-                }
-            }
-            curObj.put(CmnConst.ATTR_SHOW_NAME, key);
-            if (statisticsFieldList.contains(key)) {
-                curObj.put(CmnConst.ATTR_IS_STATISTICS_FIELD, "1");
-                newKey = key.replace(CmnConst.STATISTICS_NAME, "");
-                curObj.put(dataAreaFieldName, newKey);
-                curObj.put(CmnConst.ATTR_DATA_AREA_SUB_CNT, getSubCnt(curOperateObj.getJSONObject(newKey)));
-            } else {
-                curObj.put(dataAreaFieldName, key);
-            }
-            curObj.put(CmnConst.ATTR_ROWSPAN, 1);
-            curObj.put(CmnConst.ATTR_COLSPAN, 1);
-            curRowList.add(curObj);
-            if (value instanceof JSONObject) {
-                objValue = (JSONObject) value;
-                if (objValue.isEmpty()) {
-                    curObj.put(CmnConst.ATTR_COLSPAN, maxCol - col + 1);
-                    if (row > 1 && col > 1) {
-                        int emptyCount = 0;
-                        for (JSONObject obj : curRowList) {
-                            if (obj.isEmpty()) {
-                                emptyCount++;
-                            } else {
-                                break;
-                            }
-                        }
-                        for (int j = 0; j < emptyCount; j++) {
-                            int curRow = row - 2;
-                            topLeftCornerObj = dataAreaGroupFieldDataList.get(curRow).get(j);
-                            while (topLeftCornerObj.isEmpty() && curRow > 0) {
-                                curRow--;
-                                topLeftCornerObj = dataAreaGroupFieldDataList.get(curRow).get(j);
-                            }
-                            topLeftCornerObj.put(CmnConst.ATTR_ROWSPAN, topLeftCornerObj.getIntValue(CmnConst.ATTR_ROWSPAN) + 1);
-                        }
-                    }
-                    row++;
-                    continue;
-                }
-                if (objValue.size() == 1&& objValue.containsKey(CmnConst.ATTR_REAL_VALUE)) {
-                    row++;
-                    continue;
-                }
-                row = getDataAreaGroupFieldDataList(objValue, dataAreaGroupFieldDataList, curObj, row, col + 1, maxCol, dataAreaFieldName);
-            }
-        }
-        return row;
-    }
+	/**
+	 * 鑾峰彇鍒嗙粍琛ㄥご鍖鸿寖鍥寸殑鏍囬list
+	 *
+	 * @param dataAreaFieldConfigMap  鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param curOperateObj           褰撳墠鎿嶄綔obj
+	 * @param groupAreaRangeTitleList 鍒嗙粍琛ㄥご鍖鸿寖鍥翠笅鏁版嵁鏍囬list
+	 * @param preTitleObj             鏈�杩戞搷浣滅殑鏍囬obj
+	 * @param row                     褰撳墠琛屾暟
+	 * @param maxRow                  鏈�澶ц鏁�
+	 */
+	private void getGroupAreaRangeTitleList(Map<String, JSONObject> dataAreaFieldConfigMap, JSONObject curOperateObj, List<List<JSONObject>> groupAreaRangeTitleList, JSONObject preTitleObj, int row, int maxRow, String parentFieldName) {
+		if (curOperateObj == null || curOperateObj.isEmpty()) {
+			return;
+		}
+		String key;
+		Object value;
+		JSONObject curTitleObj;
+		String groupAreaFieldName = dataListReportService.fieldInfo2FieldName(curOperateObj.getString(CmnConst.ATTR_FIELD_INFO));
+		List<String> statisticsFieldList = dataListReportService.transfer2List(curOperateObj.get(CmnConst.ATTR_STATISTICS_FIELD));
+		String realValue = curOperateObj.getString(CmnConst.ATTR_REAL_VALUE);
+		String fieldName = dataListReportService.fieldInfo2FieldName(curOperateObj.getString(CmnConst.ATTR_FIELD_INFO));
+		String newKey;
+		JSONObject realValueObj;
+		for (Map.Entry<String, Object> entry : curOperateObj.entrySet()) {
+			curTitleObj = dataListReportService.extendJSONObject(null, preTitleObj, null);
+			if (!StringUtils.isEmpty(realValue) && !StringUtils.isEmpty(parentFieldName)) {
+				if (curTitleObj.get(CmnConst.ATTR_REAL_VALUE) == null) {
+					realValueObj = new JSONObject();
+					curTitleObj.put(CmnConst.ATTR_REAL_VALUE, realValueObj);
+				} else {
+					realValueObj = (JSONObject) curTitleObj.get(CmnConst.ATTR_REAL_VALUE);
+				}
+				realValueObj.put(parentFieldName, realValue);
+			}
+			key = entry.getKey();
+			if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key) || CmnConst.ATTR_REAL_VALUE.equals(key)) {
+				continue;
+			}
+			value = entry.getValue();
+			if (value == null) {
+				continue;
+			}
+			curTitleObj.put(CmnConst.ATTR_SHOW_NAME, key);
+			if (statisticsFieldList.contains(key)) {
+				curTitleObj.put(CmnConst.ATTR_IS_STATISTICS_FIELD, "1");
+				newKey = key.replace(CmnConst.STATISTICS_NAME, "");
+				curTitleObj.put(groupAreaFieldName, newKey);
+				curTitleObj.put(CmnConst.ATTR_GROUP_AREA_SUB_CNT, getSubCnt(curOperateObj.getJSONObject(newKey)));
+			} else {
+				curTitleObj.put(groupAreaFieldName, key);
+			}
+			groupAreaRangeTitleList.get(row).add(curTitleObj);
+			if (value instanceof List) {
+				curTitleObj.put(CmnConst.ATTR_COLSPAN, ((List) value).size());
+				curTitleObj.put(CmnConst.ATTR_ROWSPAN, maxRow - row);
+				for (String dataAreaFieldName : (List<String>) value) {
+					JSONObject cloneTitleObj = (JSONObject) curTitleObj.clone();
+					cloneTitleObj.put(CmnConst.ATTR_FIELD_INFO, dataListReportService.fieldName2FieldInfo(dataAreaFieldName));
+					cloneTitleObj.put(CmnConst.ATTR_COLSPAN, 1);
+					cloneTitleObj.put(CmnConst.ATTR_ROWSPAN, 1);
+					JSONObject dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataAreaFieldName);
+					cloneTitleObj.put(CmnConst.ATTR_SHOW_NAME, dataListReportService.getStatisticsDesc(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS), dataAreaFieldConfigObj.getString(CmnConst.ATTR_SHOW_NAME)));
+					groupAreaRangeTitleList.get(maxRow).add(cloneTitleObj);
+				}
+			} else {
+				if (value instanceof JSONObject) {
+					curTitleObj.put(CmnConst.ATTR_COLSPAN, getGroupAreaColCount((JSONObject) value, 0));
+					curTitleObj.put(CmnConst.ATTR_ROWSPAN, 1);
+					getGroupAreaRangeTitleList(dataAreaFieldConfigMap, (JSONObject) value, groupAreaRangeTitleList, curTitleObj, row + 1, maxRow, fieldName);
+				}
+			}
+		}
+	}
 
-    /**
-     * 鑾峰彇鎬昏html
-     * @param statisticsMap             缁熻map
-     * @param dataTitleList             鏁版嵁鏍囬list
-     * @param dataAreaFieldConfigMap    鏁版嵁鍖哄瓧娈电紦瀛榤ap
-     * @param dataAreaGroupFieldCount   鏁版嵁鍖哄垎缁勫瓧娈典釜鏁�
-     * @param dataAreaSubCnt            鏁版嵁鍖轰笅绾у垎缁勯」鏁�
-     * @param totalName                 鎬昏鍚嶇О
-     * @return
-     */
-    private StringBuilder getTotalStatisticsHtml(Map<JSONObject, JSONObject> statisticsMap, List<JSONObject> dataTitleList, Map<String, JSONObject> dataAreaFieldConfigMap, int dataAreaGroupFieldCount, int dataAreaSubCnt, String totalName) {
-        StringBuilder html = new StringBuilder(256);
-        html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
-        html.append("<td colspan=\"").append(dataAreaGroupFieldCount).append("\">").append(totalName).append("</td>");
-        JSONObject dataTitleObj;
-        JSONObject keyObj;
-        JSONObject dataAreaFieldConfigObj;
-        String statisticsType;
-        JSONObject valueObj;
-        String value;
-        int groupAreaSubCnt;
-        for (int i = 0;i < dataTitleList.size();i++) {
-            dataTitleObj = dataTitleList.get(i);
-            keyObj = dataListReportService.extendJSONObject(null, dataTitleObj, Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD, CmnConst.ATTR_REAL_VALUE), -1);
-            dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO)));
-            if (dataAreaFieldConfigObj != null) {
-                groupAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
-                keyObj.remove(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
-                statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
-                valueObj = statisticsMap.get(keyObj);
-                if (valueObj == null || valueObj.isEmpty()) {
-                    value = getFinalValue(keyObj, dataAreaFieldConfigObj, statisticsMap);
-                } else {
-                    if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
-                        value = getTwoTypesGroupAvgStatisticsValue(dataAreaSubCnt, groupAreaSubCnt, valueObj, dataAreaFieldConfigObj, statisticsType);
-                    } else {
-                        value = valueObj.getString(statisticsType);
-                    }
-                    valueObj.put(CmnConst.ATTR_FINAL_VALUE, value);
-                }
-            } else {
-                value = "";
-            }
-            html.append("<td");
-            if (!StringUtils.isEmpty(value)) {
-                // class
-                if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
-                    dataListReportService.extendJSONObject(keyObj, dataAreaFieldConfigObj, Collections.singletonList(CmnConst.ATTR_URL));
-                    html.append(" class=\"").append(CmnConst.CLASS_TD_CAN_TURN).append("\"");
-                }
-                // 瀛楁灞炴��
-                dataListReportService.getTdAttrObj(keyObj, dataTitleObj);
-                html.append(dataListReportService.getTdAttrByObj(keyObj));
-                // 鏍煎紡
-                value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
-            }
-            html.append(">").append(value == null ? "" : value).append("</td>");
-        }
-        html.append("\n</tr>");
-        return html;
-    }
+	/**
+	 * 鑾峰彇涓嬬骇鍒嗙粍椤规暟
+	 *
+	 * @param obj 寰呮搷浣滅殑obj
+	 * @return 涓嬬骇鍒嗙粍椤规暟
+	 */
+	private int getSubCnt(JSONObject obj) {
+		int count = 0;
+		List<String> statisticsFieldList = dataListReportService.transfer2List(obj.get(CmnConst.ATTR_STATISTICS_FIELD));
+		for (String key : obj.keySet()) {
+			if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key) || statisticsFieldList.contains(key)) {
+				continue;
+			}
+			count++;
+		}
+		return count;
+	}
 
-    /**
-     * 鑾峰彇缁熻鏂瑰紡涓衡�滄渶缁堢粺璁♀�濈殑鍊�
-     * @param keyObj
-     * @param dataAreaFieldConfigObj
-     * @param statisticsMap
-     * @return
-     */
-    private String getFinalValue(JSONObject keyObj, JSONObject dataAreaFieldConfigObj, Map<JSONObject, JSONObject> statisticsMap) {
-        JSONObject valueObj;
-        String value;
-        if (CmnConst.ATTR_STATISTICS_FINAL_STATISTICS.equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))
-                && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA))) {
-            // 缁熻鏂瑰紡涓衡�滄渶缁堢粺璁♀��
-            String formula = dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA);
-            List<String> suitList = dataListReportService.getSuitContent(formula, "\\{#((?!\\{).)+#\\}");
-            JSONObject tempObj = (JSONObject) keyObj.clone();
-            for (String suitContent : suitList) {
-                tempObj.put(CmnConst.ATTR_FIELD_INFO, suitContent);
-                valueObj = statisticsMap.get(tempObj);
-                formula = formula.replace(suitContent, (valueObj == null || valueObj.getString(CmnConst.ATTR_FINAL_VALUE) == null ? "0" : valueObj.getString(CmnConst.ATTR_FINAL_VALUE)) + "d");
-            }
-            try {
-                value = BaseUtil.executeExpression(formula.replace("/0", "/1").replaceAll("\\/\\{#[\\w]+#}", "/1").replaceAll("\\{#[\\w]+#}", "0"), Maps.newHashMap()).toString();
-            } catch (Exception e) {
-                SpringMVCContextHolder.getSystemLogger().error(e);
-                value = "";
-            }
-        } else {
-            value = "";
-        }
-        return value;
-    }
+	/**
+	 * 鑾峰彇鍐呭html
+	 *
+	 * @param dataTitleList              鏁版嵁鏍囬list
+	 * @param dataAreaFieldRecordObj     鏁版嵁鍖哄瓧娈佃褰昽bj
+	 * @param statisticsMap              缁熻map
+	 * @param totalName                  鎬昏鍚嶇О锛岄潪绌�-闇�瑕佹�昏
+	 * @param dataAreaGroupFieldNameList 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+	 * @param dataAreaFieldConfigMap     鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @return 涓氬姟鏁版嵁鍐呭html
+	 */
+	private StringBuilder getDataAreaDataHtml(List<JSONObject> dataTitleList, JSONObject dataAreaFieldRecordObj, Map<JSONObject, JSONObject> statisticsMap, String totalName, List<String> dataAreaGroupFieldNameList, Map<String, JSONObject> dataAreaFieldConfigMap) {
+		List<List<JSONObject>> dataAreaGroupFieldDataList = Lists.newArrayList();
+		getDataAreaGroupFieldDataList(dataAreaFieldRecordObj, dataAreaGroupFieldDataList, new JSONObject(), 1, 1, dataAreaGroupFieldNameList.size(), null);
 
-    /**
-     * 鑾峰彇琛屽垪涓ょ涓嶅悓鐨勪笅绾у垎缁勫钩鍧囧��
-     * @param dataAreaSubCnt            鎸夌収鏁版嵁鍖哄垎缁勭殑涓嬬骇鍒嗙粍椤规暟
-     * @param groupAreaSubCnt           鎸夌収鍒嗙粍琛ㄥご鍘诲垎缁勭殑涓嬬骇鍒嗙粍椤规暟
-     * @param curFieldStatisticsObj     褰撳墠瀛楁缁熻obj
-     * @param dataAreaFieldConfigObj    褰撳墠鏁版嵁鍖哄瓧娈电紦瀛榦bj
-     * @param statisticsType            缁熻绫诲瀷
-     * @return                          鎸夌収涓嬬骇鍒嗙粍椤硅繘琛屽钩鍧囩殑琛屽垪骞冲潎鍊�
-     */
-    private String getTwoTypesGroupAvgStatisticsValue(int dataAreaSubCnt, int groupAreaSubCnt, JSONObject curFieldStatisticsObj, JSONObject dataAreaFieldConfigObj, String statisticsType) {
-        // 鍒椾笅绾у垎缁�
-        StringBuilder value = new StringBuilder(32);
-        String dataAreaValue = getGroupAreaGroupAvgStatisticsValue(dataAreaSubCnt, curFieldStatisticsObj, dataAreaFieldConfigObj, statisticsType, CmnConst.ATTR_STATISTICS_DATA_AREA_AVG, dataAreaSubCnt == 0);
-        String groupAreaValue = getGroupAreaGroupAvgStatisticsValue(groupAreaSubCnt, curFieldStatisticsObj, dataAreaFieldConfigObj, statisticsType, CmnConst.ATTR_STATISTICS_GROUP_AREA_AVG, groupAreaSubCnt == 0);
+		List<JSONObject> groupTitleList = Lists.newArrayList();
+		JSONObject obj;
+		for (List<JSONObject> rowList : dataAreaGroupFieldDataList) {
+			obj = dataListReportService.extendJSONObject(null, rowList.get(rowList.size() - 1), Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD), -1);
+			groupTitleList.add(obj);
+		}
 
-        if (dataAreaSubCnt > 0) {
-            value.append(dataAreaValue);
-        }
-        if (dataAreaSubCnt > 0 && groupAreaSubCnt > 0) {
-            value.append("\\");
-        }
-        if (groupAreaSubCnt > 0) {
-            value.append(groupAreaValue);
-        }
-        return value.toString();
-    }
+		StringBuilder html = new StringBuilder(1024);
+		JSONObject dataAreaGroupFieldObj;
+		int rowspan;
+		int colspan;
+		String value;
+		JSONObject groupTitleObj;
+		JSONObject keyObj;
+		JSONObject valueObj;
+		String statisticsType;
+		JSONObject dataAreaFieldConfigObj;
+		int groupAreaSubCnt;
+		int dataAreaSubCnt;
+		List<JSONObject> curRowList;
+		int index;
+		for (int i = 0; i < dataAreaGroupFieldDataList.size(); i++) {
+			index = 0;
+			curRowList = dataAreaGroupFieldDataList.get(i);
+			if (!curRowList.isEmpty()) {
+				for (int j = 0; j < curRowList.size(); j++) {
+					dataAreaGroupFieldObj = curRowList.get(j);
+					if (dataAreaGroupFieldObj.isEmpty()) {
+						continue;
+					}
+					if (index == 0) {
+						if ("1".equals(dataAreaGroupFieldObj.getString(CmnConst.ATTR_IS_STATISTICS_FIELD))) {
+							html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
+						} else {
+							html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
+						}
+					}
+					rowspan = Math.max(1, dataAreaGroupFieldObj.getIntValue(CmnConst.ATTR_ROWSPAN));
+					colspan = Math.max(1, dataAreaGroupFieldObj.getIntValue(CmnConst.ATTR_COLSPAN));
+					value = dataAreaGroupFieldObj.getString(CmnConst.ATTR_SHOW_NAME);
+					html.append("<td rowspan=\"").append(rowspan).append("\" colspan=\"").append(colspan).append("\">").append(value == null ? "" : value).append("</td>");
+					index++;
+				}
+			} else {
+				html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
+			}
+			groupTitleObj = groupTitleList.get(i);
+			for (JSONObject dataTitleObj : dataTitleList) {
+				keyObj = dataListReportService.extendJSONObject((JSONObject) groupTitleObj.clone(), dataTitleObj, Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD, CmnConst.ATTR_REAL_VALUE), -1);
+				dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO)));
+				if (dataAreaFieldConfigObj != null) {
+					groupAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
+					dataAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_DATA_AREA_SUB_CNT);
+					keyObj.remove(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
+					keyObj.remove(CmnConst.ATTR_DATA_AREA_SUB_CNT);
+					keyObj.remove(CmnConst.ATTR_REAL_VALUE);
+					statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+					valueObj = statisticsMap.get(keyObj);
+					if (valueObj == null || valueObj.isEmpty()) {
+						value = getFinalValue(keyObj, dataAreaFieldConfigObj, statisticsMap);
+					} else {
+						if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
+							if (dataAreaSubCnt == 0 && groupAreaSubCnt == 0) {
+								value = valueObj.getString(statisticsType);
+							} else {
+								value = getTwoTypesGroupAvgStatisticsValue(dataAreaSubCnt, groupAreaSubCnt, valueObj, dataAreaFieldConfigObj, statisticsType);
+							}
+						} else {
+							value = valueObj.getString(statisticsType);
+						}
+						valueObj.put(CmnConst.ATTR_FINAL_VALUE, value);
+					}
+				} else {
+					value = "";
+				}
+				html.append("<td");
+				if (!StringUtils.isEmpty(value)) {
+					// class
+					if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
+						dataListReportService.extendJSONObject(keyObj, dataAreaFieldConfigObj, Collections.singletonList(CmnConst.ATTR_URL));
+						html.append(" class=\"").append(CmnConst.CLASS_TD_CAN_TURN).append("\"");
+					}
+					// 瀛楁灞炴��
+					dataListReportService.getTdAttrObj(keyObj, groupTitleObj);
+					dataListReportService.getTdAttrObj(keyObj, dataTitleObj);
+					html.append(dataListReportService.getTdAttrByObj(keyObj));
+					// 鏍煎紡
+					value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+				}
+				html.append(">").append(value == null ? "" : value).append("</td>");
+			}
+			html.append("\n</tr>");
+		}
 
-    /**
-     * 鑾峰彇鎸囧畾绫诲瀷鐨勪笅绾у垎缁勫钩鍧囧��
-     * @param subCnt                    涓嬬骇鍒嗙粍椤规暟
-     * @param curFieldStatisticsObj     褰撳墠瀛楁缁熻obj
-     * @param dataAreaFieldConfigObj    褰撳墠鏁版嵁鍖哄瓧娈电紦瀛榦bj
-     * @param statisticsType            缁熻绫诲瀷
-     * @param avgType                   CmnConst.ATTR_STATISTICS_DATA_AREA_AVG-琛岋紱CmnConst.ATTR_STATISTICS_GROUP_AREA_AVG-鍒�
-     * @return                          鎸夌収涓嬬骇鍒嗙粍椤硅繘琛屽钩鍧囩殑骞冲潎鍊�
-     */
-    private String getGroupAreaGroupAvgStatisticsValue(int subCnt, JSONObject curFieldStatisticsObj, JSONObject dataAreaFieldConfigObj, String statisticsType, String avgType, boolean lastStage) {
-        String value;
-        if (subCnt > 0) {
-            curFieldStatisticsObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
-            dataListReportService.getAvgValue(curFieldStatisticsObj, dataAreaFieldConfigObj, lastStage);
-            value = curFieldStatisticsObj.getString(statisticsType);
-            curFieldStatisticsObj.put(avgType, value);
-        } else {
-            value = curFieldStatisticsObj.getString(statisticsType);
-        }
-        return value == null ? "" : value;
-    }
+		// 鎬昏
+		if (!StringUtils.isEmpty(totalName)) {
+			html.append(getTotalStatisticsHtml(statisticsMap, dataTitleList, dataAreaFieldConfigMap, dataAreaGroupFieldNameList.size(), getSubCnt(dataAreaFieldRecordObj), totalName));
+		}
+
+		return html;
+	}
+
+	/**
+	 * 鑾峰彇鍐呭html
+	 *
+	 * @param dataTitleList              鏁版嵁鏍囬list
+	 * @param dataAreaFieldRecordObj     鏁版嵁鍖哄瓧娈佃褰昽bj
+	 * @param statisticsMap              缁熻map
+	 * @param totalName                  鎬昏鍚嶇О锛岄潪绌�-闇�瑕佹�昏
+	 * @param dataAreaGroupFieldNameList 鏁版嵁鍖哄垎缁勫瓧娈靛悕绉發ist
+	 * @param dataAreaFieldConfigMap     鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @return 涓氬姟鏁版嵁鍐呭html
+	 */
+	private List<List<ReportColumn>> getDataAreaData(List<JSONObject> dataTitleList, JSONObject dataAreaFieldRecordObj, Map<JSONObject, JSONObject> statisticsMap, String totalName, List<String> dataAreaGroupFieldNameList, Map<String, JSONObject> dataAreaFieldConfigMap) {
+		List<List<JSONObject>> dataAreaGroupFieldDataList = Lists.newArrayList();
+		getDataAreaGroupFieldDataList(dataAreaFieldRecordObj, dataAreaGroupFieldDataList, new JSONObject(), 1, 1, dataAreaGroupFieldNameList.size(), null);
+
+		List<JSONObject> groupTitleList = Lists.newArrayList();
+		JSONObject obj;
+		for (List<JSONObject> rowList : dataAreaGroupFieldDataList) {
+			obj = dataListReportService.extendJSONObject(null, rowList.get(rowList.size() - 1), Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD), -1);
+			groupTitleList.add(obj);
+		}
+
+		StringBuilder html = new StringBuilder(1024);
+		JSONObject dataAreaGroupFieldObj;
+		int rowspan;
+		int colspan;
+		String value;
+		JSONObject groupTitleObj;
+		JSONObject keyObj;
+		JSONObject valueObj;
+		String statisticsType;
+		JSONObject dataAreaFieldConfigObj;
+		int groupAreaSubCnt;
+		int dataAreaSubCnt;
+		List<JSONObject> curRowList;
+		int index;
+		for (int i = 0; i < dataAreaGroupFieldDataList.size(); i++) {
+			index = 0;
+			curRowList = dataAreaGroupFieldDataList.get(i);
+			if (!curRowList.isEmpty()) {
+				for (int j = 0; j < curRowList.size(); j++) {
+					dataAreaGroupFieldObj = curRowList.get(j);
+					if (dataAreaGroupFieldObj.isEmpty()) {
+						continue;
+					}
+					if (index == 0) {
+						if ("1".equals(dataAreaGroupFieldObj.getString(CmnConst.ATTR_IS_STATISTICS_FIELD))) {
+							html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
+						} else {
+							html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
+						}
+					}
+					rowspan = Math.max(1, dataAreaGroupFieldObj.getIntValue(CmnConst.ATTR_ROWSPAN));
+					colspan = Math.max(1, dataAreaGroupFieldObj.getIntValue(CmnConst.ATTR_COLSPAN));
+					value = dataAreaGroupFieldObj.getString(CmnConst.ATTR_SHOW_NAME);
+					html.append("<td rowspan=\"").append(rowspan).append("\" colspan=\"").append(colspan).append("\">").append(value == null ? "" : value).append("</td>");
+					index++;
+				}
+			} else {
+				html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_COMMON).append("\">\n    ");
+			}
+			groupTitleObj = groupTitleList.get(i);
+			for (JSONObject dataTitleObj : dataTitleList) {
+				keyObj = dataListReportService.extendJSONObject((JSONObject) groupTitleObj.clone(), dataTitleObj, Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD, CmnConst.ATTR_REAL_VALUE), -1);
+				dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO)));
+				if (dataAreaFieldConfigObj != null) {
+					groupAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
+					dataAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_DATA_AREA_SUB_CNT);
+					keyObj.remove(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
+					keyObj.remove(CmnConst.ATTR_DATA_AREA_SUB_CNT);
+					keyObj.remove(CmnConst.ATTR_REAL_VALUE);
+					statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+					valueObj = statisticsMap.get(keyObj);
+					if (valueObj == null || valueObj.isEmpty()) {
+						value = getFinalValue(keyObj, dataAreaFieldConfigObj, statisticsMap);
+					} else {
+						if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
+							if (dataAreaSubCnt == 0 && groupAreaSubCnt == 0) {
+								value = valueObj.getString(statisticsType);
+							} else {
+								value = getTwoTypesGroupAvgStatisticsValue(dataAreaSubCnt, groupAreaSubCnt, valueObj, dataAreaFieldConfigObj, statisticsType);
+							}
+						} else {
+							value = valueObj.getString(statisticsType);
+						}
+						valueObj.put(CmnConst.ATTR_FINAL_VALUE, value);
+					}
+				} else {
+					value = "";
+				}
+				html.append("<td");
+				if (!StringUtils.isEmpty(value)) {
+					// class
+					if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
+						dataListReportService.extendJSONObject(keyObj, dataAreaFieldConfigObj, Collections.singletonList(CmnConst.ATTR_URL));
+						html.append(" class=\"").append(CmnConst.CLASS_TD_CAN_TURN).append("\"");
+					}
+					// 瀛楁灞炴��
+					dataListReportService.getTdAttrObj(keyObj, groupTitleObj);
+					dataListReportService.getTdAttrObj(keyObj, dataTitleObj);
+					html.append(dataListReportService.getTdAttrByObj(keyObj));
+					// 鏍煎紡
+					value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+				}
+				html.append(">").append(value == null ? "" : value).append("</td>");
+			}
+			html.append("\n</tr>");
+		}
+
+		// 鎬昏
+		if (!StringUtils.isEmpty(totalName)) {
+			html.append(getTotalStatisticsHtml(statisticsMap, dataTitleList, dataAreaFieldConfigMap, dataAreaGroupFieldNameList.size(), getSubCnt(dataAreaFieldRecordObj), totalName));
+		}
+
+		return null;
+	}
+
+	/**
+	 * 鑾峰彇鏁版嵁鍖哄垎缁勫瓧娈垫暟鎹甽ist
+	 *
+	 * @param curOperateObj              褰撳墠鎿嶄綔obj
+	 * @param dataAreaGroupFieldDataList 鏁版嵁鍖哄垎缁勫瓧娈垫暟鎹甽ist
+	 * @param preObj                     鏈�杩戞搷浣滅殑obj
+	 * @param row                        褰撳墠琛屾暟
+	 * @param maxCol                     鏈�澶у垪鏁�
+	 * @return 鏁版嵁鍖哄垎缁勫瓧娈垫暟鎹甽ist
+	 */
+	private int getDataAreaGroupFieldDataList(JSONObject curOperateObj, List<List<JSONObject>> dataAreaGroupFieldDataList, JSONObject preObj, int row, int col, int maxCol, String parentFieldName) {
+		String key;
+		Object value;
+		JSONObject curObj;
+		JSONObject topLeftCornerObj;
+		String dataAreaFieldName = dataListReportService.fieldInfo2FieldName(curOperateObj.getString(CmnConst.ATTR_FIELD_INFO));
+		List<String> statisticsFieldList = dataListReportService.transfer2List(curOperateObj.get(CmnConst.ATTR_STATISTICS_FIELD));
+		String realValue = curOperateObj.getString(CmnConst.ATTR_REAL_VALUE);
+		JSONObject objValue;
+		String newKey;
+		List<JSONObject> curRowList;
+		JSONObject realValueObj;
+		for (Map.Entry<String, Object> entry : curOperateObj.entrySet()) {
+			curObj = dataListReportService.extendJSONObject(null, preObj, null);
+			key = entry.getKey();
+			if (CmnConst.ATTR_FIELD_INFO.equals(key) || CmnConst.ATTR_STATISTICS_FIELD.equals(key) || CmnConst.ATTR_REAL_VALUE.equals(key)) {
+				continue;
+			}
+			value = entry.getValue();
+			if (value == null) {
+				continue;
+			}
+			if (!StringUtils.isEmpty(realValue) && !StringUtils.isEmpty(parentFieldName)) {
+				if (curObj.get(CmnConst.ATTR_REAL_VALUE) == null) {
+					realValueObj = new JSONObject();
+					curObj.put(CmnConst.ATTR_REAL_VALUE, realValueObj);
+				} else {
+					realValueObj = (JSONObject) curObj.get(CmnConst.ATTR_REAL_VALUE);
+				}
+				realValueObj.put(parentFieldName, realValue);
+			}
+			if (dataAreaGroupFieldDataList.size() < row) {
+				curRowList = Lists.newArrayList();
+				dataAreaGroupFieldDataList.add(curRowList);
+			} else {
+				curRowList = dataAreaGroupFieldDataList.get(row - 1);
+			}
+			if (curRowList.size() < col - 1) {
+				for (int i = 0; i < col - 1; i++) {
+					curRowList.add(new JSONObject());
+				}
+			}
+			curObj.put(CmnConst.ATTR_SHOW_NAME, key);
+			if (statisticsFieldList.contains(key)) {
+				curObj.put(CmnConst.ATTR_IS_STATISTICS_FIELD, "1");
+				newKey = key.replace(CmnConst.STATISTICS_NAME, "");
+				curObj.put(dataAreaFieldName, newKey);
+				curObj.put(CmnConst.ATTR_DATA_AREA_SUB_CNT, getSubCnt(curOperateObj.getJSONObject(newKey)));
+			} else {
+				curObj.put(dataAreaFieldName, key);
+			}
+			curObj.put(CmnConst.ATTR_ROWSPAN, 1);
+			curObj.put(CmnConst.ATTR_COLSPAN, 1);
+			curRowList.add(curObj);
+			if (value instanceof JSONObject) {
+				objValue = (JSONObject) value;
+				if (objValue.isEmpty()) {
+					curObj.put(CmnConst.ATTR_COLSPAN, maxCol - col + 1);
+					if (row > 1 && col > 1) {
+						int emptyCount = 0;
+						for (JSONObject obj : curRowList) {
+							if (obj.isEmpty()) {
+								emptyCount++;
+							} else {
+								break;
+							}
+						}
+						for (int j = 0; j < emptyCount; j++) {
+							int curRow = row - 2;
+							topLeftCornerObj = dataAreaGroupFieldDataList.get(curRow).get(j);
+							while (topLeftCornerObj.isEmpty() && curRow > 0) {
+								curRow--;
+								topLeftCornerObj = dataAreaGroupFieldDataList.get(curRow).get(j);
+							}
+							topLeftCornerObj.put(CmnConst.ATTR_ROWSPAN, topLeftCornerObj.getIntValue(CmnConst.ATTR_ROWSPAN) + 1);
+						}
+					}
+					row++;
+					continue;
+				}
+				if (objValue.size() == 1 && objValue.containsKey(CmnConst.ATTR_REAL_VALUE)) {
+					row++;
+					continue;
+				}
+				row = getDataAreaGroupFieldDataList(objValue, dataAreaGroupFieldDataList, curObj, row, col + 1, maxCol, dataAreaFieldName);
+			}
+		}
+		return row;
+	}
+
+	/**
+	 * 鑾峰彇鎬昏html
+	 *
+	 * @param statisticsMap           缁熻map
+	 * @param dataTitleList           鏁版嵁鏍囬list
+	 * @param dataAreaFieldConfigMap  鏁版嵁鍖哄瓧娈电紦瀛榤ap
+	 * @param dataAreaGroupFieldCount 鏁版嵁鍖哄垎缁勫瓧娈典釜鏁�
+	 * @param dataAreaSubCnt          鏁版嵁鍖轰笅绾у垎缁勯」鏁�
+	 * @param totalName               鎬昏鍚嶇О
+	 * @return
+	 */
+	private StringBuilder getTotalStatisticsHtml(Map<JSONObject, JSONObject> statisticsMap, List<JSONObject> dataTitleList, Map<String, JSONObject> dataAreaFieldConfigMap, int dataAreaGroupFieldCount, int dataAreaSubCnt, String totalName) {
+		StringBuilder html = new StringBuilder(256);
+		html.append("\n<tr class=\"").append(CmnConst.CLASS_TR_DATA_STATISTICS).append("\">\n    ");
+		html.append("<td colspan=\"").append(dataAreaGroupFieldCount).append("\">").append(totalName).append("</td>");
+		JSONObject dataTitleObj;
+		JSONObject keyObj;
+		JSONObject dataAreaFieldConfigObj;
+		String statisticsType;
+		JSONObject valueObj;
+		String value;
+		int groupAreaSubCnt;
+		for (int i = 0; i < dataTitleList.size(); i++) {
+			dataTitleObj = dataTitleList.get(i);
+			keyObj = dataListReportService.extendJSONObject(null, dataTitleObj, Arrays.asList(CmnConst.ATTR_ROWSPAN, CmnConst.ATTR_COLSPAN, CmnConst.ATTR_SHOW_NAME, CmnConst.ATTR_IS_STATISTICS_FIELD, CmnConst.ATTR_REAL_VALUE), -1);
+			dataAreaFieldConfigObj = dataAreaFieldConfigMap.get(dataListReportService.fieldInfo2FieldName(dataTitleObj.getString(CmnConst.ATTR_FIELD_INFO)));
+			if (dataAreaFieldConfigObj != null) {
+				groupAreaSubCnt = keyObj.getIntValue(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
+				keyObj.remove(CmnConst.ATTR_GROUP_AREA_SUB_CNT);
+				statisticsType = dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS);
+				valueObj = statisticsMap.get(keyObj);
+				if (valueObj == null || valueObj.isEmpty()) {
+					value = getFinalValue(keyObj, dataAreaFieldConfigObj, statisticsMap);
+				} else {
+					if (CmnConst.ATTR_STATISTICS_AVG.equals(statisticsType) && "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_AVG_TYPE))) {
+						value = getTwoTypesGroupAvgStatisticsValue(dataAreaSubCnt, groupAreaSubCnt, valueObj, dataAreaFieldConfigObj, statisticsType);
+					} else {
+						value = valueObj.getString(statisticsType);
+					}
+					valueObj.put(CmnConst.ATTR_FINAL_VALUE, value);
+				}
+			} else {
+				value = "";
+			}
+			html.append("<td");
+			if (!StringUtils.isEmpty(value)) {
+				// class
+				if (!StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_URL))) {
+					dataListReportService.extendJSONObject(keyObj, dataAreaFieldConfigObj, Collections.singletonList(CmnConst.ATTR_URL));
+					html.append(" class=\"").append(CmnConst.CLASS_TD_CAN_TURN).append("\"");
+				}
+				// 瀛楁灞炴��
+				dataListReportService.getTdAttrObj(keyObj, dataTitleObj);
+				html.append(dataListReportService.getTdAttrByObj(keyObj));
+				// 鏍煎紡
+				value = dataListReportService.formatValue(dataAreaFieldConfigObj, value);
+			}
+			html.append(">").append(value == null ? "" : value).append("</td>");
+		}
+		html.append("\n</tr>");
+		return html;
+	}
+
+	/**
+	 * 鑾峰彇缁熻鏂瑰紡涓衡�滄渶缁堢粺璁♀�濈殑鍊�
+	 *
+	 * @param keyObj
+	 * @param dataAreaFieldConfigObj
+	 * @param statisticsMap
+	 * @return
+	 */
+	private String getFinalValue(JSONObject keyObj, JSONObject dataAreaFieldConfigObj, Map<JSONObject, JSONObject> statisticsMap) {
+		JSONObject valueObj;
+		String value;
+		if (CmnConst.ATTR_STATISTICS_FINAL_STATISTICS.equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_STATISTICS))
+				&& "1".equals(dataAreaFieldConfigObj.getString(CmnConst.ATTR_IS_CUSTOM_FIELD)) && !StringUtils.isEmpty(dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA))) {
+			// 缁熻鏂瑰紡涓衡�滄渶缁堢粺璁♀��
+			String formula = dataAreaFieldConfigObj.getString(CmnConst.ATTR_FORMULA);
+			List<String> suitList = dataListReportService.getSuitContent(formula, "\\{#((?!\\{).)+#\\}");
+			JSONObject tempObj = (JSONObject) keyObj.clone();
+			for (String suitContent : suitList) {
+				tempObj.put(CmnConst.ATTR_FIELD_INFO, suitContent);
+				valueObj = statisticsMap.get(tempObj);
+				formula = formula.replace(suitContent, (valueObj == null || valueObj.getString(CmnConst.ATTR_FINAL_VALUE) == null ? "0" : valueObj.getString(CmnConst.ATTR_FINAL_VALUE)) + "d");
+			}
+			try {
+				value = BaseUtil.executeExpression(formula.replace("/0", "/1").replaceAll("\\/\\{#[\\w]+#}", "/1").replaceAll("\\{#[\\w]+#}", "0"), Maps.newHashMap()).toString();
+			} catch (Exception e) {
+				SpringMVCContextHolder.getSystemLogger().error(e);
+				value = "";
+			}
+		} else {
+			value = "";
+		}
+		return value;
+	}
+
+	/**
+	 * 鑾峰彇琛屽垪涓ょ涓嶅悓鐨勪笅绾у垎缁勫钩鍧囧��
+	 *
+	 * @param dataAreaSubCnt         鎸夌収鏁版嵁鍖哄垎缁勭殑涓嬬骇鍒嗙粍椤规暟
+	 * @param groupAreaSubCnt        鎸夌収鍒嗙粍琛ㄥご鍘诲垎缁勭殑涓嬬骇鍒嗙粍椤规暟
+	 * @param curFieldStatisticsObj  褰撳墠瀛楁缁熻obj
+	 * @param dataAreaFieldConfigObj 褰撳墠鏁版嵁鍖哄瓧娈电紦瀛榦bj
+	 * @param statisticsType         缁熻绫诲瀷
+	 * @return 鎸夌収涓嬬骇鍒嗙粍椤硅繘琛屽钩鍧囩殑琛屽垪骞冲潎鍊�
+	 */
+	private String getTwoTypesGroupAvgStatisticsValue(int dataAreaSubCnt, int groupAreaSubCnt, JSONObject curFieldStatisticsObj, JSONObject dataAreaFieldConfigObj, String statisticsType) {
+		// 鍒椾笅绾у垎缁�
+		StringBuilder value = new StringBuilder(32);
+		String dataAreaValue = getGroupAreaGroupAvgStatisticsValue(dataAreaSubCnt, curFieldStatisticsObj, dataAreaFieldConfigObj, statisticsType, CmnConst.ATTR_STATISTICS_DATA_AREA_AVG, dataAreaSubCnt == 0);
+		String groupAreaValue = getGroupAreaGroupAvgStatisticsValue(groupAreaSubCnt, curFieldStatisticsObj, dataAreaFieldConfigObj, statisticsType, CmnConst.ATTR_STATISTICS_GROUP_AREA_AVG, groupAreaSubCnt == 0);
+
+		if (dataAreaSubCnt > 0) {
+			value.append(dataAreaValue);
+		}
+		if (dataAreaSubCnt > 0 && groupAreaSubCnt > 0) {
+			value.append("\\");
+		}
+		if (groupAreaSubCnt > 0) {
+			value.append(groupAreaValue);
+		}
+		return value.toString();
+	}
+
+	/**
+	 * 鑾峰彇鎸囧畾绫诲瀷鐨勪笅绾у垎缁勫钩鍧囧��
+	 *
+	 * @param subCnt                 涓嬬骇鍒嗙粍椤规暟
+	 * @param curFieldStatisticsObj  褰撳墠瀛楁缁熻obj
+	 * @param dataAreaFieldConfigObj 褰撳墠鏁版嵁鍖哄瓧娈电紦瀛榦bj
+	 * @param statisticsType         缁熻绫诲瀷
+	 * @param avgType                CmnConst.ATTR_STATISTICS_DATA_AREA_AVG-琛岋紱CmnConst.ATTR_STATISTICS_GROUP_AREA_AVG-鍒�
+	 * @return 鎸夌収涓嬬骇鍒嗙粍椤硅繘琛屽钩鍧囩殑骞冲潎鍊�
+	 */
+	private String getGroupAreaGroupAvgStatisticsValue(int subCnt, JSONObject curFieldStatisticsObj, JSONObject dataAreaFieldConfigObj, String statisticsType, String avgType, boolean lastStage) {
+		String value;
+		if (subCnt > 0) {
+			curFieldStatisticsObj.put(CmnConst.ATTR_STATISTICS_SUB_CNT, subCnt);
+			dataListReportService.getAvgValue(curFieldStatisticsObj, dataAreaFieldConfigObj, lastStage);
+			value = curFieldStatisticsObj.getString(statisticsType);
+			curFieldStatisticsObj.put(avgType, value);
+		} else {
+			value = curFieldStatisticsObj.getString(statisticsType);
+		}
+		return value == null ? "" : value;
+	}
 }
diff --git a/src/main/java/com/product/server/report/service/ReportConfigService.java b/src/main/java/com/product/server/report/service/ReportConfigService.java
index 76180f4..6a8915c 100644
--- a/src/main/java/com/product/server/report/service/ReportConfigService.java
+++ b/src/main/java/com/product/server/report/service/ReportConfigService.java
@@ -317,7 +317,7 @@
 		fseFunction.setValue(CmnConst.FUNCTION_NAME, fseReport.getString(CmnConst.REPORT_NAME));    //鍔熻兘鍚嶇О
 		fseFunction.setValue(CmnConst.FUNCTION_DESCRIPTION, fseReport.getString(CmnConst.REPORT_NAME));    //鍔熻兘鎻忚堪
 		fseFunction.setValue(CmnConst.STATUS_UUID, 1);            //鏄惁鍚敤
-		fseFunction.setValue(CmnConst.FUNCTION_TYPE_UUID, 1);    //鍔熻兘绫诲瀷-涓氬姟鍔熻兘
+		fseFunction.setValue(CmnConst.FUNCTION_TYPE_UUID, 5);    //鍔熻兘绫诲瀷-涓氬姟鍚庡彴绠$悊 绠$悊鍛樺拰鏅�氱敤鎴烽兘鑳藉垎閰嶈鎶ヨ〃鐨勬潈闄�
 		fseFunction.setValue(CmnConst.CLIENT_TYPE_UUID, "Web");        //瀹㈡埛绔被鍨�
 		fseFunction.setValue(CmnConst.VERSION_UUID, "001");
 		fseFunction.setValue(CmnConst.DATA_TYPE, 1);// 鏁版嵁绫诲瀷
@@ -384,11 +384,11 @@
 		// 鎻愬彇鍙戝竷鐨勮鑹茬浉鍏虫暟鎹�
 		List<String> roleUUIDList = Lists.newArrayList();
 		List<String> clientUUIDList = Lists.newArrayList();
-		String[] singleRoleInfoArr;
+		clientUUIDList.add(SpringMVCContextHolder.getCurrentUser().getClientUuid());
+//		String[] singleRoleInfoArr;
 		for (String singleRoleInfo : fse.getString(CmnConst.ROLE_UUID).split("#")) {
-			singleRoleInfoArr = singleRoleInfo.split(",");
-			roleUUIDList.add(singleRoleInfoArr[2]);
-			clientUUIDList.add(singleRoleInfoArr[0]);
+//			singleRoleInfoArr = singleRoleInfo.split(",");
+			roleUUIDList.add(singleRoleInfo);
 		}
 
 		// 2.缁戝畾瑙掕壊(缁欐煇涓�瑙掕壊璧嬩簣璇ュ姛鑳�)

--
Gitblit v1.9.2