瀏覽代碼

Merge branch '1.0.0_online' of http://smartcost.f3322.net:3000/SmartCost/ConstructionOperation into 1.0.0_online

zhongzewei 6 年之前
父節點
當前提交
90eb4b408f

+ 14 - 0
modules/reports/rpt_component/helper/jpc_helper_field.js

@@ -13,6 +13,19 @@ let JpcFieldHelper = {
             dataField[valueIdx] = newValue;
         }
     },
+    resetSumFormat: function(ref_tab_fields, sum_tab_field) {
+        let rst = false;
+        if (ref_tab_fields && ref_tab_fields.length > 0) {
+            for (let tab_field of ref_tab_fields) {
+                if (tab_field[JV.PROP_FIELD_ID] === sum_tab_field[JV.PROP_FIELD_ID]) {
+                    rst = true;
+                    sum_tab_field[JV.PROP_FORMAT] = tab_field[JV.PROP_FORMAT];
+                    break;
+                }
+            }
+        }
+        return rst;
+    },
     resetFormat: function (tab_field, map_field, customizeCfg) {
         if (map_field && map_field[JV.PROP_PRECISION] && map_field[JV.PROP_PRECISION].type === "fixed") {
             let formatStrs = ["#."], ffStr = (customizeCfg && customizeCfg.fillZero)?"0":"#";
@@ -24,6 +37,7 @@ let JpcFieldHelper = {
             } else {
                 tab_field[JV.PROP_FORMAT] = formatStrs.join("");
             }
+            map_field[JV.PROP_FORMAT] = tab_field[JV.PROP_FORMAT]; //这里顺手把format也赋给map_field,后期统计用得着
         }
     },
     resetFlexibleFormat: function (tab_field, ref_field_data, flexiblePrecisionRefObj, valueIdx, customizeCfg) {

+ 23 - 3
modules/reports/rpt_component/jpc_flow_tab.js

@@ -690,9 +690,9 @@ JpcFlowTabSrv.prototype.createNew = function(){
             // 2.2 Column tab
             tabRstLst.push(me.outputColumn(rptTpl, dataObj, page, segIdx, bands, unitFactor, 0));
             // 2.3 Sum Seg
-            tabRstLst.push(me.outputSegSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls));
+            tabRstLst.push(me.outputSegSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT));
             // 2.4 Sum Page
-            tabRstLst.push(me.outputPageSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls));
+            tabRstLst.push(me.outputPageSum(rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT));
             // 2.5 Group
             // 2.6 Discrete
             tabRstLst.push(JpcDiscreteHelper.outputDiscreteInfo(rptTpl[FLOW_NODE_STR][JV.NODE_DISCRETE_INFO], bands, dataObj, unitFactor, me.pageStatusLst[page - 1], segIdx, 1, 0, $CURRENT_RPT, customizeCfg));
@@ -941,12 +941,22 @@ JpcFlowTabSrv.prototype.createNew = function(){
         let me = this, rst = [];
         let FLOW_NODE_STR = me.isEx?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
         let tab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_SEG_SUM];
+        let refTab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_CONTENT];
+        let refTabEx = (rptTpl[JV.NODE_FLOW_INFO_EX])?rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_CONTENT]:null;
         let band = bands[tab[JV.PROP_BAND_NAME]];
         if (band) {
             let pageStatus = me.pageStatusLst[page - 1];
             if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]]) {
+                let ref_tab_fields = refTab[JV.PROP_FLOW_FIELDS];
+                let ref_tab_fields_ex = refTabEx?refTabEx[JV.PROP_FLOW_FIELDS]:null;
                 let tab_fields = me.seg_sum_tab_fields;
                 for (let i = 0; i < tab_fields.length; i++) {
+                    if (!JpcFieldHelper.resetSumFormat(ref_tab_fields, tab_fields[i])) {
+                        if (!JpcFieldHelper.resetSumFormat(ref_tab_fields_ex, tab_fields[i])) {
+                            let map_data_field = JE.F(tab_fields[i][JV.PROP_FIELD_ID], $CURRENT_RPT);
+                            tab_fields[i][JV.PROP_FORMAT] = map_data_field[JV.PROP_FORMAT];
+                        }
+                    }
                     let sumVal = 0;
                     if (me.segSumValLst[segIdx] && me.segSumValLst[segIdx].length > i) {
                         sumVal = me.segSumValLst[segIdx][i];
@@ -961,16 +971,26 @@ JpcFlowTabSrv.prototype.createNew = function(){
         }
         return rst;
     };
-    JpcFlowTabResult.outputPageSum = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls) {
+    JpcFlowTabResult.outputPageSum = function (rptTpl, dataObj, page, segIdx, bands, unitFactor, controls, $CURRENT_RPT) {
         let me = this, rst = [];
         let FLOW_NODE_STR = me.isEx?JV.NODE_FLOW_INFO_EX:JV.NODE_FLOW_INFO;
         let tab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_PAGE_SUM];
+        let refTab = rptTpl[FLOW_NODE_STR][JV.NODE_FLOW_CONTENT];
+        let refTabEx = (rptTpl[JV.NODE_FLOW_INFO_EX])?rptTpl[JV.NODE_FLOW_INFO_EX][JV.NODE_FLOW_CONTENT]:null;
         let band = bands[tab[JV.PROP_BAND_NAME]];
         if (band) {
             let pageStatus = me.pageStatusLst[page - 1];
             if (pageStatus[band[JV.BAND_PROP_DISPLAY_TYPE]]) {
+                let ref_tab_fields = refTab[JV.PROP_FLOW_FIELDS];
+                let ref_tab_fields_ex = refTabEx?refTabEx[JV.PROP_FLOW_FIELDS]:null;
                 let tab_fields = me.page_sum_tab_fields;
                 for (let i = 0; i < tab_fields.length; i++) {
+                    if (!JpcFieldHelper.resetSumFormat(ref_tab_fields, tab_fields[i])) {
+                        if (!JpcFieldHelper.resetSumFormat(ref_tab_fields_ex, tab_fields[i])) {
+                            let map_data_field = JE.F(tab_fields[i][JV.PROP_FIELD_ID], $CURRENT_RPT);
+                            tab_fields[i][JV.PROP_FORMAT] = map_data_field[JV.PROP_FORMAT];
+                        }
+                    }
                     let cellItem = JpcCommonOutputHelper.createCommonOutput(tab_fields[i], me.pageSumValLst[page - 1][i], controls);
                     cellItem[JV.PROP_AREA] = JpcAreaHelper.outputArea(tab_fields[i][JV.PROP_AREA], band, unitFactor, 1, 0, 1, 0, me.multiCols, 0, true, false);
                     rst.push(cellItem);

+ 3 - 3
test/demo/stringTest.js

@@ -31,10 +31,10 @@ let strUtil = require('../../public/stringUtil');
 //     t.end();
 // })
 
-test('string encodeURI', function(t){
-    let str = "";
+test('string ', function(t){
+    let str = "{abc}";
     console.log(str);
-    console.log(encodeURI(str));
+    console.log(str.slice(1, -1));
     t.end();
 })
 

+ 1 - 2
web/maintain/project_feature_lib/html/edit.html

@@ -23,14 +23,13 @@
         </div>
         </div>
         <input type="hidden" id="libID" value="<%= libID %>">
+        <input type="hidden" id="originalFeature" value="<%= featureList %>">
     </div>
 </div>
 
 
 
 <script type="text/javascript">
-    //自适应高度
-    let featureList = '<%- featureList %>';
 
 </script>
 <script type="text/javascript" src="/lib/json/json2.js"></script>

+ 24 - 16
web/maintain/project_feature_lib/js/project_feature_edit.js

@@ -6,7 +6,12 @@ featureObj = {
 };
 
 $(document).ready(function () {
-   $("#featureList").val(JSON.stringify(JSON.parse(featureList),null,4));
+    try {
+        $("#featureList").val(JSON.stringify(JSON.parse($("#originalFeature").val()),null,4));
+    }catch (err){
+        $("#featureList").val(featureList);
+        console.log(err);
+    }
 
    $("#format").click( function() {
        try {
@@ -22,8 +27,11 @@ $(document).ready(function () {
         try {
             let libID = $("#libID").val();
             let jsonText =  $("#featureList").val();
+            if(jsonText.indexOf("'")!=-1){
+                alert("输入的格式不能包含 ' 位于:"+jsonText.substr(jsonText.indexOf("'")-15,18));
+                return;
+            }
             let newFeature = await ajaxPost("/projectFeature/saveLib",{query:{ID:libID},data:{feature:JSON.parse(jsonText)}});
-            console.log(newFeature);
         }catch (err){
             console.log(err);
             alert("保存失败,请查看输入数据");
@@ -32,20 +40,20 @@ $(document).ready(function () {
     $("#createNormal").click(async function() {
         let projectFeature = [
             {dispName: '工程专业', key: 'engineering', value: ''},//只读,用户新建单位工程时选择的值
-            {dispName: '工程类型', key: 'projType', value: ''},
-            {dispName: '结构类型', key: 'structureType', value: ''},
-            {dispName: '基础类型', key: 'baseType', value: ''},
-            {dispName: '建筑特征', key: 'buildingFeature', value: ''},
-            {dispName: '建筑面积(m2)', key: 'buildingArea', value: ''},
-            {dispName: '其中地下室建筑面积(m2)', key: 'basementBuildingArea', value: ''},
-            {dispName: '总层数', key: 'totalFloors', value: ''},
-            {dispName: '地下室层数(+/-0.00以下)', key: 'basementFloors', value: ''},
-            {dispName: '建筑层数(+/-0.00以下)', key: 'buildingFloors', value: ''},
-            {dispName: '建筑物总高度(m)', key: 'buildingHeight', value: ''},
-            {dispName: '地下室总高度(m)', key: 'basementHeight', value: ''},
-            {dispName: '首层高度(m)', key: 'firstFloorHeight', value: ''},
-            {dispName: '裙楼高度(m)', key: 'podiumBuildingHeight', value: ''},
-            {dispName: '标准层高度(m)', key: 'standardFloorHeight', value: ''},
+            {dispName: '工程类型', key: 'projType', value: '',cellType:'comboBox',options:"住宅@公共建筑@厂房@办公"},
+            {dispName: '结构类型', key: 'structureType', value: '',cellType:'comboBox',options:"排架结构@框架结构@现浇、框架结构@预制、砖混结构@外砖内模@内浇外挂@钢结构"},
+            {dispName: '基础类型', key: 'baseType', value: '',cellType:'comboBox',options:"带基@框排架柱距6m以内@框排架柱距6m以外@满基筏式@满基板式@满基箱式@独立基础"},
+            {dispName: '建筑特征', key: 'buildingFeature', value: '',cellType:'comboBox',options:"点式@凹式@凸式@Y式@其他"},
+            {dispName: '建筑面积(m2)', key: 'buildingArea', value: '',cellType:'number'},
+            {dispName: '其中地下室建筑面积(m2)', key: 'basementBuildingArea', value: '',cellType:'number'},
+            {dispName: '总层数', key: 'totalFloors', value: '',cellType:'number'},
+            {dispName: '地下室层数(+/-0.00以下)', key: 'basementFloors', value: '',cellType:'number'},
+            {dispName: '建筑层数(+/-0.00以下)', key: 'buildingFloors', value: '',cellType:'number'},
+            {dispName: '建筑物总高度(m)', key: 'buildingHeight', value: '',cellType:'number'},
+            {dispName: '地下室总高度(m)', key: 'basementHeight', value: '',cellType:'number'},
+            {dispName: '首层高度(m)', key: 'firstFloorHeight', value: '',cellType:'number'},
+            {dispName: '裙楼高度(m)', key: 'podiumBuildingHeight', value: '',cellType:'number'},
+            {dispName: '标准层高度(m)', key: 'standardFloorHeight', value: '',cellType:'number'},
             {dispName: '基础材料及装饰', key: 'baseMaterial', value: ''},
             {dispName: '楼地面材料及装饰', key: 'flooringMaterial', value: ''},
             {dispName: '外墙材料及装饰', key: 'exteriorWallMaterial', value: ''},

+ 5 - 5
web/maintain/report/html/rpt_tpl_detail_virtual_column.html

@@ -16,13 +16,13 @@
         <div style="height: 5px"></div>
         <div class='row' id="fieldControlDiv" style="cursor: not-allowed">
             <div class="form-group col-md-3">
-                <label ><input type="radio" name="horizonOptions" id="hOptionLeft" onchange="fieldLocationOprObj.changeCtrl(this)" checked="true" disabled>左</label>&nbsp
-                <label ><input type="radio" name="horizonOptions" id="hOptionCenter" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>中</label>&nbsp
-                <label ><input type="radio" name="horizonOptions" id="hOptionRight" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>右</label>&nbsp&nbsp
+                <label ><input type="radio" name="horizonOptions1" id="hOptionLeft" onchange="fieldLocationOprObj.changeCtrl(this)" checked="true" disabled>左</label>&nbsp
+                <label ><input type="radio" name="horizonOptions1" id="hOptionCenter" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>中</label>&nbsp
+                <label ><input type="radio" name="horizonOptions1" id="hOptionRight" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>右</label>&nbsp&nbsp
                 <label>|</label>&nbsp&nbsp
                 <label style="display:none" ><input type="radio" name="verticalOptions" id="vOptionUp" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>上</label>
-                <label ><input type="radio" name="verticalOptions" id="vOptionCenter" onchange="fieldLocationOprObj.changeCtrl(this)" checked="true" disabled>中</label>&nbsp
-                <label ><input type="radio" name="verticalOptions" id="vOptionDown" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>下</label>
+                <label ><input type="radio" name="verticalOptions1" id="vOptionCenter" onchange="fieldLocationOprObj.changeCtrl(this)" checked="true" disabled>中</label>&nbsp
+                <label ><input type="radio" name="verticalOptions1" id="vOptionDown" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>下</label>
             </div>
             <div class="form-group col-md-2">
                 <label style="display:none" class="form-check-label"><input type="checkbox" class="form-check-input" id="eleShrinkEx" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>自动缩放</label>

+ 12 - 10
web/maintain/report/html/rpt_tpl_detail_virtual_summary.html

@@ -10,17 +10,19 @@
         <label id="id_summary_setup_lbl" style="color:yellowgreen;font-weight:bold">...</label>
         <div style="height: 5px"></div>
         <div class='row' id="sumFieldControlDiv" style="cursor: not-allowed">
-            <div class="form-group col-md-3">
-                <label ><input type="radio" name="horizonOptions" id="hOptionLeftSum" onchange="" checked="true" disabled>左</label>&nbsp
-                <label ><input type="radio" name="horizonOptions" id="hOptionCenterSum" onchange="" disabled>中</label>&nbsp
-                <label ><input type="radio" name="horizonOptions" id="hOptionRightSum" onchange="" disabled>右</label>&nbsp&nbsp
+            <div class="form-group col-md-5">
+                <label ><input type="radio" name="horizonOptions2" id="hOptionLeftSum" onchange="virtualSummaryOprObj.changeCellCfg()" checked="true" disabled>左</label>&nbsp
+                <label ><input type="radio" name="horizonOptions2" id="hOptionCenterSum" onchange="virtualSummaryOprObj.changeCellCfg()" disabled>中</label>&nbsp
+                <label ><input type="radio" name="horizonOptions2" id="hOptionRightSum" onchange="virtualSummaryOprObj.changeCellCfg()" disabled>右</label>&nbsp&nbsp
                 <label>|</label>&nbsp&nbsp
-                <label ><input type="radio" name="verticalOptions" id="vOptionUpSum" onchange="" disabled>上</label>
-                <label ><input type="radio" name="verticalOptions" id="vOptionCenterSum" onchange="" checked="true" disabled>中</label>&nbsp
-                <label ><input type="radio" name="verticalOptions" id="vOptionDownSum" onchange="" disabled>下</label>
-            </div>
-            <div class="form-group col-md-2">
-                <label class="form-check-label"><input type="checkbox" class="form-check-input" id="eleIsNarrowSumEx" onchange="" disabled>窄体</label>
+                <label style="display:none" ><input type="radio" name="verticalOptions2" id="vOptionUpSum" onchange="virtualSummaryOprObj.changeCellCfg()" disabled>上</label>&nbsp
+                <label ><input type="radio" name="verticalOptions2" id="vOptionCenterSum" onchange="virtualSummaryOprObj.changeCellCfg()" checked="true" disabled>中</label>&nbsp
+                <label ><input type="radio" name="verticalOptions2" id="vOptionDownSum" onchange="virtualSummaryOprObj.changeCellCfg()" disabled>下</label>&nbsp&nbsp
+                <label>|</label>&nbsp&nbsp
+                <label ><input type="radio" name="cellTypes2" id="rdIsText" onchange="virtualSummaryOprObj.changeCellType(`text`)" checked="true" disabled>文本</label>&nbsp
+                <label ><input type="radio" name="cellTypes2" id="rdIsField" onchange="virtualSummaryOprObj.changeCellType(`field`)" disabled>指标</label>&nbsp&nbsp
+                <label>|</label>&nbsp&nbsp
+                <label class="form-check-label"><input type="checkbox" class="form-check-input" id="eleIsNarrowSumEx" onchange="virtualSummaryOprObj.changeCellCfg()" disabled>&nbsp窄体</label>&nbsp&nbsp
             </div>
         </div>
         <div id="rptTplSummaryWorkbook"></div>

+ 10 - 94
web/maintain/report/js/rpt_tpl_field_location.js

@@ -73,7 +73,7 @@ let fieldLocationOprObj = {
                 }
                 // sheet.clear();
                 let cellType = new GC.Spread.Sheets.CellTypes.ComboBox();
-                let selectableFields = me.private_getSelectedFields(rptTpl);
+                let selectableFields = virtualCommonOprObj.getSelectedFields(rptTpl);
                 cellType.items(selectableFields);
                 //设置 最后一行为 行数据选择combobox
                 let iSelectedRow = sheet.getRowCount() - 1;
@@ -102,21 +102,14 @@ let fieldLocationOprObj = {
                     sheet.getRange(idx - 1, -1, 1, -1).backColor(undefined);
                 }
                 for (let itemNode of columnParentNode.items) {
-                    let idx1 = xPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_LEFT, bandW, xPos));
-                    let idx2 = xPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_RIGHT, bandW, xPos));
-                    let idy1 = yPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_TOP, bandH, yPos));
-                    let idy2 = yPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_BOTTOM, bandH, yPos));
-                    if (idx2 - idx1 > 1 || idy2 - idy1 > 1) {
-                        sheet.addSpan(idy1, idx1, idy2 - idy1, idx2 - idx1, GC.Spread.Sheets.SheetArea.viewport);
-                    }
-                    me.private_setupCell(sheet.getCell(idy1, idx1), rptTpl, itemNode);
+                    virtualCommonOprObj.addSpan(itemNode, sheet, bandW, bandH, xPos, yPos, GC.Spread.Sheets.SheetArea.viewport);
                 }
             } else {
                 sheet.setRowCount(2);
                 sheet.setColumnCount(1);
                 me.columnFieldCtrls.push(me.private_create_dft_ctrl());
                 let cellType = new GC.Spread.Sheets.CellTypes.ComboBox();
-                let selectableFields = me.private_getSelectedFields(rptTpl);
+                let selectableFields = virtualCommonOprObj.getSelectedFields(rptTpl);
                 cellType.items(selectableFields);
                 //设置 最后一行为 行数据选择combobox
                 let iSelectedRow = sheet.getRowCount() - 1;
@@ -148,7 +141,7 @@ let fieldLocationOprObj = {
         sheet.addRows(sheet.getRowCount() - 1, 1);
         let rc = sheet.getRowCount();
         for (let cc = 0; cc < sheet.getColumnCount(); cc++) {
-            me.private_setupCellDft(sheet.getCell(rc - 2, cc));
+            virtualCommonOprObj.setupCellDft(sheet.getCell(rc - 2, cc));
         }
     },
     deleteRow: function () {
@@ -171,14 +164,14 @@ let fieldLocationOprObj = {
         sheet.suspendPaint();
         sheet.addColumns(sheet.getColumnCount(), 1);
         let cellType = new GC.Spread.Sheets.CellTypes.ComboBox();
-        let selectableFields = me.private_getSelectedFields(rptTpl);
+        let selectableFields = virtualCommonOprObj.getSelectedFields(rptTpl);
         cellType.items(selectableFields);
         //设置 最后一行为 行数据选择combobox
         // sheet.getRange(sheet.getRowCount() - 1, -1, 1, -1).locked(true);
         let colIdx = sheet.getColumnCount() - 1;
         sheet.getCell(sheet.getRowCount() - 1, colIdx).cellType(cellType);
         for (let iRow = 0; iRow < sheet.getRowCount() - 1; iRow++) {
-            me.private_setupCellDft(sheet.getCell(iRow, colIdx));
+            virtualCommonOprObj.setupCellDft(sheet.getCell(iRow, colIdx));
         }
         //
         me.columnFieldCtrls.push(me.private_create_dft_ctrl());
@@ -216,7 +209,7 @@ let fieldLocationOprObj = {
         let me = fieldLocationOprObj,
             sheet = me.columnWorkBook.getActiveSheet();
         let selectedRanges = sheet.getSelections();
-        let spans =sheet.getSpans();
+        let spans = sheet.getSpans();
         if (selectedRanges.length > 0 && spans.length > 0) {
             let selectedSpans = [];
             for(let i = 0; i < spans.length; i++)
@@ -422,83 +415,6 @@ let fieldLocationOprObj = {
             $("#eleIsAutoHeightEx")[0].disabled = "disabled" ;
         }
     },
-    private_getSelectedFields: function (rptTpl) {
-        let rst = [];
-        if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS] !== undefined && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS].length > 0) {
-            for (let field of rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
-                rst.push(field[JV.PROP_NAME]);
-            }
-        }
-        if (rptTpl[JV.NODE_NO_MAPPING_FIELDS] !== undefined && rptTpl[JV.NODE_NO_MAPPING_FIELDS].length > 0) {
-            for (let field of rptTpl[JV.NODE_NO_MAPPING_FIELDS]) {
-                rst.push(field[JV.PROP_NAME]);
-            }
-        }
-        return rst;
-    },
-    private_setupCell: function (cell, rptTpl, textNode) {
-        let me = this;
-        me.private_setCellFont(cell, textNode);
-        me.private_setCellControl(cell, textNode);
-        me.private_setCellStyle(cell, textNode);
-        let value = textNode[JV.PROP_NAME];
-        if (textNode[JV.PROP_NAME].indexOf(`|`) >= 0) {
-            value = textNode[JV.PROP_NAME].split('|').join('\n');
-        }
-        cell.wordWrap(true);
-        cell.value(value);
-    },
-    private_setupCellDft: function (cell) {
-        cell.font(`9pt 宋体`);
-        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
-        cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
-        cell.wordWrap(true);
-        cell.value(``);
-    },
-    private_setCellControl: function (cell, textNode) {
-        let ctrl = null;
-        if (typeof textNode[JV.PROP_CONTROL] === 'string') {
-            let idx = rpt_tpl_cfg_helper.reportCfg.controlArr.indexOf(textNode[JV.PROP_CONTROL]);
-            ctrl = rpt_tpl_cfg_helper.reportCfg.ctrls[idx];
-        } else {
-            ctrl = textNode[JV.PROP_CONTROL];
-        }
-        if (ctrl) {
-            switch (ctrl.Horizon) {
-                case `center`:
-                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
-                    break;
-                case `right`:
-                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.right);
-                    break;
-                default:
-                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.left);
-                    break;
-            }
-            switch (ctrl.Vertical) {
-                case `center`:
-                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
-                    break;
-                case `bottom`:
-                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.bottom);
-                    break;
-                default:
-                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.top);
-                    break;
-            }
-        }
-    },
-    private_setCellStyle: function (cell, textNode) {
-        //默认是normal,暂时不管
-    },
-    private_setCellFont: function (cell, textNode) {
-        for (let font of rpt_tpl_cfg_helper.reportCfg.fonts) {
-            if (font.ID === textNode[JV.PROP_FONT]) {
-                cell.font(Math.round(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]] * 3 / 4) + 'pt ' + font[JV.FONT_PROPS[JV.FONT_PROP_IDX_NAME]]);
-                break;
-            }
-        }
-    },
     private_create_content_node: function (colWidthArr, cellValue, colIdx, rptTpl) {
         let me = this;
         let rst = {"Name": cellValue, "Title": '', "FieldID": -1, "font": "Content", "control": "Column", "style" : "Default_Normal", "isAutoHeight" : false,
@@ -576,7 +492,7 @@ let fieldLocationOprObj = {
             let sheet = me.columnWorkBook.getActiveSheet();
             if (sheet.getRowCount() > 1 && sheet.getColumnCount() > 0) {
                 let texts = [], colWidthArr = [], rowHeightArr = [];
-                virtualCommonOprObj.collectSheetTxt(sheet, texts, colWidthArr, rowHeightArr);
+                virtualCommonOprObj.collectSheetTxt(sheet, texts, 1, colWidthArr, rowHeightArr);
                 let nodes = [];
                 //表栏重置
                 //0. 先清除原先所有的column text
@@ -602,9 +518,9 @@ let fieldLocationOprObj = {
                     }
                 }
                 dataInfoMapTreeOprObj.treeObj.addNodes(me.contentParentNode, -1, contentNodes, true);
-                displayMessage("应用提交成功!", "green", 2000, "id_column_setup_lbl");
+                displayMessage("应用提交成功!", "green", 5000, "id_column_setup_lbl");
             } else {
-                displayMessage("模板行列数量不足!", "red", 2000, "id_column_setup_lbl");
+                displayMessage("模板行列数量不足!", "red", 5000, "id_column_setup_lbl");
             }
         }
     }

+ 154 - 12
web/maintain/report/js/rpt_tpl_virtual_common.js

@@ -62,21 +62,24 @@ let virtualCommonOprObj = {
         }
         return rst;
     },
-    createTxtNode: function (text, parentNode, colWidthArr, rowHeightArr) {
+    setupHeightWidth: function (dest, text, colWidthArr, rowHeightArr) {
         let width = colWidthArr[colWidthArr.length - 1], height = rowHeightArr[rowHeightArr.length - 1];
-        let rst = dataInfoMapTreeOprObj.getDummyTextNode(parentNode);
-        rst[JV.PROP_AREA][JV.PROP_RIGHT] = (colWidthArr[text.col + text.colCount - 1] / width * 100).toFixed(2);
+        dest[JV.PROP_AREA][JV.PROP_RIGHT] = (colWidthArr[text.col + text.colCount - 1] / width * 100).toFixed(2);
         if (text.col > 0) {
-            rst[JV.PROP_AREA][JV.PROP_LEFT] = (colWidthArr[text.col - 1] / width * 100).toFixed(2);
+            dest[JV.PROP_AREA][JV.PROP_LEFT] = (colWidthArr[text.col - 1] / width * 100).toFixed(2);
         } else {
-            rst[JV.PROP_AREA][JV.PROP_LEFT] = 0;
+            dest[JV.PROP_AREA][JV.PROP_LEFT] = 0;
         }
-        rst[JV.PROP_AREA][JV.PROP_BOTTOM] = (rowHeightArr[text.row + text.rowCount - 1] / height * 100).toFixed(2);
+        dest[JV.PROP_AREA][JV.PROP_BOTTOM] = (rowHeightArr[text.row + text.rowCount - 1] / height * 100).toFixed(2);
         if (text.row > 0) {
-            rst[JV.PROP_AREA][JV.PROP_TOP] = (rowHeightArr[text.row - 1] / height * 100).toFixed(2);
+            dest[JV.PROP_AREA][JV.PROP_TOP] = (rowHeightArr[text.row - 1] / height * 100).toFixed(2);
         } else {
-            rst[JV.PROP_AREA][JV.PROP_TOP] = 0;
+            dest[JV.PROP_AREA][JV.PROP_TOP] = 0;
         }
+    },
+    createTxtNode: function (text, parentNode, colWidthArr, rowHeightArr) {
+        let me = this, rst = dataInfoMapTreeOprObj.getDummyTextNode(parentNode);
+        me.setupHeightWidth(rst, text, colWidthArr, rowHeightArr);
         if (stringUtil.isEmptyString(text[`text`])) {
             rst[JV.PROP_NAME] = '';
         } else {
@@ -85,15 +88,20 @@ let virtualCommonOprObj = {
         rst[JV.PROP_LABEL] = rst[JV.PROP_NAME];
         return rst;
     },
-    collectSheetTxt: function (sheet, texts, colWidthArr, rowHeightArr) {
+    collectSheetTxt: function (sheet, texts, reserveRows, colWidthArr, rowHeightArr) {
         let spans= sheet.getSpans();
         let private_build_pre_text = function (row, col, rowCount, colCount) {
-            texts.push({"row": row, "col": col, "rowCount": rowCount, "colCount": colCount, "text": sheet.getValue(row, col)});
+            let cell = sheet.getCell(row, col);
+            let textValue = sheet.getValue(row, col);
+            if (textValue && cell.cellType().typeName === '7') {
+                textValue = `{` + textValue + `}`;
+            }
+            texts.push({"row": row, "col": col, "rowCount": rowCount, "colCount": colCount, "text": textValue});
         };
         for (let span of spans) {
             private_build_pre_text(span.row, span.col, span.rowCount, span.colCount);
         }
-        for (let iRow = 0; iRow < sheet.getRowCount() - 1; iRow++) {
+        for (let iRow = 0; iRow < sheet.getRowCount() - reserveRows; iRow++) {
             rowHeightArr.push(sheet.getRowHeight(iRow));
             if (iRow > 0) {
                 rowHeightArr[iRow] = rowHeightArr[iRow] + rowHeightArr[iRow - 1];
@@ -117,5 +125,139 @@ let virtualCommonOprObj = {
                 return t1.col - t2.col;
             }
         });
+    },
+    addSpan: function (itemNode, sheet, bandW, bandH, xPos, yPos, sheetAreaType) {
+        let me = this;
+        let idx1 = xPos.indexOf(me.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_LEFT, bandW, xPos));
+        let idx2 = xPos.indexOf(me.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_RIGHT, bandW, xPos));
+        let idy1 = yPos.indexOf(me.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_TOP, bandH, yPos));
+        let idy2 = yPos.indexOf(me.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_BOTTOM, bandH, yPos));
+        if (idx2 - idx1 > 1 || idy2 - idy1 > 1) {
+            sheet.addSpan(idy1, idx1, idy2 - idy1, idx2 - idx1, sheetAreaType);
+        }
+        let cell = sheet.getCell(idy1, idx1, sheetAreaType);
+        if (sheetAreaType === GC.Spread.Sheets.SheetArea.viewport) {
+            if (itemNode.FieldID) {
+                me.changeCellType(cell, 'field');
+            } else {
+                me.changeCellType(cell, 'text');
+            }
+        }
+        me.setupCell(cell, itemNode);
+    },
+    changeBandHeight: function (bandName, newHeight) {
+        let nodes = bandTreeOprObj.treeObj.getNodes()[0][JV.BAND_PROP_SUB_BANDS];
+        let private_set_band_height = function(bNode) {
+            let rst = false;
+            if (bNode[JV.PROP_NAME] === bandName) {
+                bNode[JV.BAND_PROP_HEIGHT] = newHeight;
+                rst = true;
+            } else if (bNode[JV.BAND_PROP_SUB_BANDS] && bNode[JV.BAND_PROP_SUB_BANDS].length > 0){
+                for (let subNode of bNode[JV.BAND_PROP_SUB_BANDS]) {
+                    rst = private_set_band_height(subNode);
+                    if (rst) break;
+                }
+            }
+            return rst;
+        };
+        for (let bandNode of nodes) {
+            if (private_set_band_height(bandNode)) break;
+        }
+    },
+    changeCellType: function (cell, newType) {
+        switch (newType) {
+            case `field`:
+                let rptTpl = (zTreeOprObj.currentNode)?zTreeOprObj.currentNode.rptTpl:null;
+                let cellType = new GC.Spread.Sheets.CellTypes.ComboBox();
+                let selectableFields = virtualCommonOprObj.getSelectedFields(rptTpl);
+                cellType.items(selectableFields);
+                cell.cellType(cellType);
+                cell.backColor("LightCyan");
+                break;
+            case `text`:
+            default:
+                cell.cellType(new GC.Spread.Sheets.CellTypes.Text());
+                cell.value(``);
+                cell.backColor(undefined);
+                break;
+        }
+    },
+    setupCell: function (cell, itemNode) {
+        let me = this;
+        me.private_setCellFont(cell, itemNode);
+        me.private_setCellControl(cell, itemNode);
+        me.private_setCellStyle(cell, itemNode);
+        let value = itemNode[JV.PROP_NAME];
+        if (itemNode[JV.PROP_NAME].indexOf(`|`) >= 0) {
+            value = itemNode[JV.PROP_NAME].split('|').join('\n');
+        }
+        cell.wordWrap(true);
+        cell.value(value);
+    },
+    private_setCellControl: function (cell, textNode) {
+        let ctrl = null;
+        if (typeof textNode[JV.PROP_CONTROL] === 'string') {
+            let idx = rpt_tpl_cfg_helper.reportCfg.controlArr.indexOf(textNode[JV.PROP_CONTROL]);
+            ctrl = rpt_tpl_cfg_helper.reportCfg.ctrls[idx];
+        } else {
+            ctrl = textNode[JV.PROP_CONTROL];
+        }
+        if (ctrl) {
+            switch (ctrl.Horizon) {
+                case `center`:
+                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
+                    break;
+                case `right`:
+                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.right);
+                    break;
+                default:
+                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.left);
+                    break;
+            }
+            switch (ctrl.Vertical) {
+                case `center`:
+                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
+                    break;
+                case `bottom`:
+                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.bottom);
+                    break;
+                default:
+                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.top);
+                    break;
+            }
+        }
+    },
+    private_setCellStyle: function (cell, textNode) {
+        //默认是normal,暂时不管
+    },
+    private_setCellFont: function (cell, textNode) {
+        for (let font of rpt_tpl_cfg_helper.reportCfg.fonts) {
+            if (font.ID === textNode[JV.PROP_FONT]) {
+                cell.font(Math.round(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]] * 3 / 4) + 'pt ' + font[JV.FONT_PROPS[JV.FONT_PROP_IDX_NAME]]);
+                break;
+            }
+        }
+    },
+    getSelectedFields: function (rptTpl) {
+        let rst = [];
+        if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS] !== undefined && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS].length > 0) {
+            for (let field of rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
+                rst.push(field[JV.PROP_NAME]);
+            }
+        }
+        if (rptTpl[JV.NODE_NO_MAPPING_FIELDS] !== undefined && rptTpl[JV.NODE_NO_MAPPING_FIELDS].length > 0) {
+            for (let field of rptTpl[JV.NODE_NO_MAPPING_FIELDS]) {
+                rst.push(field[JV.PROP_NAME]);
+            }
+        }
+        return rst;
+    },
+    setupCellDft: function (cell) {
+        cell.font(`9pt 宋体`);
+        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
+        cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
+        cell.wordWrap(true);
+        cell.cellType(new GC.Spread.Sheets.CellTypes.Text());
+        cell.value(``);
     }
-}
+};

+ 200 - 90
web/maintain/report/js/rpt_tpl_virtual_summary.js

@@ -7,28 +7,32 @@ let virtualSummaryOprObj = {
     summaryParentNode: null,
     iniSpreadJs: function (summaryParentNode) {
         let me = this;
-        if (me.summaryWorkBook === null) {
-            me.summaryWorkBook = new GC.Spread.Sheets.Workbook($('#rptTplSummaryWorkbook')[0], {sheetCount: 1});
-            me.summaryWorkBook.options.tabStripVisible = false;
-            me.summaryWorkBook.options.allowCopyPasteExcelStyle = false;
-            me.summaryWorkBook.options.allowUserDragDrop = false;
-            me.summaryWorkBook.options.allowContextMenu = false;
-            let sheet = me.summaryWorkBook.getActiveSheet();
-            sheet.options.allowCellOverflow = false;
-            sheet.options.clipBoardOptions = GC.Spread.Sheets.ClipboardPasteOptions.values;
-            sheet.bind(GC.Spread.Sheets.Events.EnterCell, me.onCellEnter);
+        if (me.summaryWorkBook !== null) {
+            me.summaryWorkBook.destroy();
+            me.summaryWorkBook = null;
         }
+        me.summaryWorkBook = new GC.Spread.Sheets.Workbook($('#rptTplSummaryWorkbook')[0], {sheetCount: 1});
+        me.summaryWorkBook.options.tabStripVisible = false;
+        me.summaryWorkBook.options.allowCopyPasteExcelStyle = false;
+        me.summaryWorkBook.options.allowUserDragDrop = false;
+        me.summaryWorkBook.options.allowContextMenu = false;
+        let sheet = me.summaryWorkBook.getActiveSheet();
+        sheet.options.allowCellOverflow = false;
+        sheet.options.clipBoardOptions = GC.Spread.Sheets.ClipboardPasteOptions.values;
+        sheet.bind(GC.Spread.Sheets.Events.CellClick, me.onCellEnter);
         me.summaryParentNode = summaryParentNode;
     },
     restoreSummary: function () {
         let me = this;
         let rptTpl = (zTreeOprObj.currentNode)?zTreeOprObj.currentNode.rptTpl:null;
+        me.private_setup_control_options(false);
         me.setupSummary(rptTpl, me.summaryParentNode);
     },
     setupSummary: function (rptTpl, summaryParentNode) {
         let me = this, columnParentNode = null;
         let selectedBand = virtualCommonOprObj.getBandEx(summaryParentNode[JV.PROP_BAND_NAME], rptTpl);
         if (summaryParentNode && selectedBand) {
+            me.private_setup_control_options(false);
             let preNode = summaryParentNode.getPreNode();
             while (preNode) {
                 if (preNode[JV.PROP_NAME] === JV.NODE_FLOW_COLUMN) {
@@ -40,7 +44,9 @@ let virtualSummaryOprObj = {
             }
             let fieldNode = summaryParentNode.items[0], textNode = summaryParentNode.items[1];
             if (columnParentNode) {
-                let yColumnPos = [], xPos = [], ySummaryPos = [0], xSummaryPos = [0];
+                let yColumnPos = [], xPos = [], ySummaryPos = [0]
+                    // , xSummaryPos = [0]
+                ;
                 let sheet = me.summaryWorkBook.getActiveSheet();
                 let columnBand = virtualCommonOprObj.getBandEx(columnParentNode[JV.PROP_BAND_NAME], rptTpl);
                 let bandH = Math.round(parseFloat(columnBand[JV.BAND_PROP_HEIGHT]) / 2.54 * 96);
@@ -60,7 +66,8 @@ let virtualSummaryOprObj = {
                     virtualCommonOprObj.pushPos(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_TOP, bandH, yColumnPos);
                     virtualCommonOprObj.pushPos(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_BOTTOM, bandH, yColumnPos);
                 }
-
+                sheet.suspendPaint();
+                sheet.clearSelection();
                 sheet.setRowCount(yColumnPos.length - 1, GC.Spread.Sheets.SheetArea.colHeader);
                 sheet.setColumnCount(xPos.length - 1, GC.Spread.Sheets.SheetArea.viewport);
                 // sheet.clear();
@@ -79,56 +86,107 @@ let virtualSummaryOprObj = {
                     sheet.getRange(idx - 1, -1, 1, -1).backColor(undefined);
                 }
                 for (let itemNode of columnParentNode.items) {
-                    let idx1 = xPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_LEFT, bandW, xPos));
-                    let idx2 = xPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_RIGHT, bandW, xPos));
-                    let idy1 = yColumnPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_TOP, bandH, yColumnPos));
-                    let idy2 = yColumnPos.indexOf(virtualCommonOprObj.getActPosEx(itemNode, itemNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_BOTTOM, bandH, yColumnPos));
-                    if (idx2 - idx1 > 1 || idy2 - idy1 > 1) {
-                        sheet.addSpan(idy1, idx1, idy2 - idy1, idx2 - idx1, GC.Spread.Sheets.SheetArea.colHeader);
-                    }
-                    me.private_setupCell(sheet.getCell(idy1, idx1, GC.Spread.Sheets.SheetArea.colHeader), rptTpl, itemNode);
+                    virtualCommonOprObj.addSpan(itemNode, sheet, bandW, bandH, xPos, yColumnPos, GC.Spread.Sheets.SheetArea.colHeader);
                 }
                 //2. 设置已有的统计信息
                 let sumBandH = Math.round(parseFloat(selectedBand[JV.BAND_PROP_HEIGHT]) / 2.54 * 96);
                 for (let fNode of fieldNode.items) {
-                    virtualCommonOprObj.pushPos(fNode, fNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_LEFT, bandW, xSummaryPos);
-                    virtualCommonOprObj.pushPos(fNode, fNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_RIGHT, bandW, xSummaryPos);
                     virtualCommonOprObj.pushPos(fNode, fNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_TOP, sumBandH, ySummaryPos);
                     virtualCommonOprObj.pushPos(fNode, fNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_BOTTOM, sumBandH, ySummaryPos);
                 }
                 for (let tNode of textNode.items) {
-                    virtualCommonOprObj.pushPos(tNode, tNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_LEFT, bandW, xSummaryPos);
-                    virtualCommonOprObj.pushPos(tNode, tNode[JV.PROP_AREA][JV.PROP_H_CALCULATION], JV.PROP_RIGHT, bandW, xSummaryPos);
                     virtualCommonOprObj.pushPos(tNode, tNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_TOP, sumBandH, ySummaryPos);
                     virtualCommonOprObj.pushPos(tNode, tNode[JV.PROP_AREA][JV.PROP_V_CALCULATION], JV.PROP_BOTTOM, sumBandH, ySummaryPos);
                 }
                 sheet.setRowCount(ySummaryPos.length - 1, GC.Spread.Sheets.SheetArea.viewport);
+                for (let idx = 1; idx < ySummaryPos.length; idx++) {
+                    sheet.setRowHeight(idx - 1, ySummaryPos[idx] - ySummaryPos[idx - 1]);
+                }
+                for (let tNode of textNode.items) {
+                    virtualCommonOprObj.addSpan(tNode, sheet, bandW, sumBandH, xPos, ySummaryPos, GC.Spread.Sheets.SheetArea.viewport);
+                }
+                for (let fNode of fieldNode.items) {
+                    virtualCommonOprObj.addSpan(fNode, sheet, bandW, sumBandH, xPos, ySummaryPos, GC.Spread.Sheets.SheetArea.viewport);
+                }
+                sheet.resumePaint();
             }
         }
     },
     addRow: function () {
         let me = this,
             sheet = me.summaryWorkBook.getActiveSheet();
+        sheet.suspendPaint();
         sheet.addRows(sheet.getRowCount() - 1, 1);
         let rc = sheet.getRowCount();
         for (let cc = 0; cc < sheet.getColumnCount(); cc++) {
-            me.private_setupCellDft(sheet.getCell(rc - 2, cc));
+            virtualCommonOprObj.setupCellDft(sheet.getCell(rc - 2, cc));
         }
+        sheet.resumePaint();
     },
     deleteRow: function () {
         let me = this,
             sheet = me.summaryWorkBook.getActiveSheet(),
             selectedRanges = sheet.getSelections()
         ;
+        sheet.suspendPaint();
         if (selectedRanges.length > 0) {
             sheet.deleteRows(selectedRanges[0].row, 1);
         }
+        sheet.resumePaint();
     },
     onCellEnter: function (sender, args) {
         let me = virtualSummaryOprObj,
             sheet = me.summaryWorkBook.getActiveSheet();
-        if (args.row === sheet.getRowCount() - 1) {
+        me.setupCfg(sheet, args.row, args.col);
+    },
+    setupCfg: function (sheet, row, col) {
+        let me = virtualSummaryOprObj, cell = sheet.getCell(row, col);
+        let font = cell.font();
+        // let style = sheet.getStyle(row, col);
+        // console.log('font: ' + font);
+        me.private_setup_control_options(true);
+        //1. 横向
+        switch (cell.hAlign()) {
+            case GC.Spread.Sheets.HorizontalAlign.left:
+                $(`#hOptionLeftSum`)[0].checked = true;
+                break;
+            case GC.Spread.Sheets.HorizontalAlign.center:
+                $(`#hOptionCenterSum`)[0].checked = true;
+                break;
+            case GC.Spread.Sheets.HorizontalAlign.right:
+                $(`#hOptionRightSum`)[0].checked = true;
+                break;
+            default:
+                $(`#hOptionLeftSum`)[0].checked = true;
+                break;
+        }
+        //2. 纵向
+        switch (cell.vAlign()) {
+            case GC.Spread.Sheets.VerticalAlign.top:
+                $(`#vOptionUpSum`)[0].checked = true;
+                break;
+            case GC.Spread.Sheets.VerticalAlign.center:
+                $(`#vOptionCenterSum`)[0].checked = true;
+                break;
+            case GC.Spread.Sheets.VerticalAlign.bottom:
+                $(`#vOptionDownSum`)[0].checked = true;
+                break;
+            default:
+                $(`#vOptionCenterSum`)[0].checked = true;
+                break;
+        }
+        //3. cell type
+        if (cell.cellType().typeName === '1') {
+            $(`#rdIsText`)[0].checked = true;
         } else {
+            $(`#rdIsField`)[0].checked = true; //combo-box cell type name: `7`
+        }
+        // console.log('cell type: ' + cell.cellType());
+        //4. 窄体
+        if (font.indexOf('Narrow') > 0) {
+            $(`#eleIsNarrowSumEx`)[0].checked = true;
+        } else {
+            $(`#eleIsNarrowSumEx`)[0].checked = false;
         }
     },
     mergeCells: function () {
@@ -145,8 +203,9 @@ let virtualSummaryOprObj = {
         let me = virtualSummaryOprObj,
             sheet = me.summaryWorkBook.getActiveSheet();
         let selectedRanges = sheet.getSelections();
-        let spans =sheet.getSpans();
+        let spans = sheet.getSpans();
         if (selectedRanges.length > 0 && spans.length > 0) {
+            sheet.suspendPaint();
             let selectedSpans = [];
             for(let i = 0; i < spans.length; i++)
             {
@@ -160,6 +219,40 @@ let virtualSummaryOprObj = {
             for (let span of selectedSpans) {
                 sheet.removeSpan(span.row, span.col, GC.Spread.Sheets.SheetArea.viewport);
             }
+            sheet.resumePaint();
+        }
+    },
+    changeCellType: function (newType) {
+        let me = virtualSummaryOprObj,
+            sheet = me.summaryWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            sheet.suspendPaint();
+            let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            virtualCommonOprObj.changeCellType(cell, newType);
+            sheet.resumePaint();
+        }
+    },
+    changeCellCfg: function () {
+        let me = virtualSummaryOprObj,
+            sheet = me.summaryWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            sheet.suspendPaint();
+            let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            let hA = GC.Spread.Sheets.HorizontalAlign.left, vA = GC.Spread.Sheets.VerticalAlign.top;
+            if ($(`#hOptionCenterSum`)[0].checked) hA = GC.Spread.Sheets.HorizontalAlign.center;
+            if ($(`#hOptionRightSum`)[0].checked) hA = GC.Spread.Sheets.HorizontalAlign.right;
+            if ($(`#vOptionCenterSum`)[0].checked ) vA = GC.Spread.Sheets.VerticalAlign.center;
+            if ($(`#vOptionDownSum`)[0].checked ) vA = GC.Spread.Sheets.VerticalAlign.bottom;
+            cell.hAlign(hA);
+            cell.vAlign(vA);
+            if ($(`#eleIsNarrowSumEx`)[0].checked) {
+                cell.font('Arial Narrow');
+            } else {
+                cell.font('9pt 宋体');
+            }
+            sheet.resumePaint();
         }
     },
     changeCtrl: function (dom) {
@@ -207,69 +300,66 @@ let virtualSummaryOprObj = {
         }
     },
 
-    private_setupCellDft: function (cell) {
-        cell.font(`9pt 宋体`);
-        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
-        cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
-        cell.wordWrap(true);
-        cell.value(``);
-    },
-    private_setupCell: function (cell, rptTpl, textNode) {
-        let me = this;
-        me.private_setCellFont(cell, textNode);
-        me.private_setCellControl(cell, textNode);
-        me.private_setCellStyle(cell, textNode);
-        let value = textNode[JV.PROP_NAME];
-        if (textNode[JV.PROP_NAME].indexOf(`|`) >= 0) {
-            value = textNode[JV.PROP_NAME].split('|').join('\n');
-        }
-        cell.wordWrap(true);
-        cell.value(value);
-    },
-
-    private_setCellControl: function (cell, textNode) {
-        let ctrl = null;
-        if (typeof textNode[JV.PROP_CONTROL] === 'string') {
-            let idx = rpt_tpl_cfg_helper.reportCfg.controlArr.indexOf(textNode[JV.PROP_CONTROL]);
-            ctrl = rpt_tpl_cfg_helper.reportCfg.ctrls[idx];
+    private_setup_control_options: function (enable) {
+        if (enable) {
+            $("#sumFieldControlDiv")[0].style.cursor = "";
+            $("#hOptionLeftSum")[0].removeAttribute("disabled");
+            $("#hOptionCenterSum")[0].removeAttribute("disabled");
+            $("#hOptionRightSum")[0].removeAttribute("disabled");
+            $("#vOptionUpSum")[0].removeAttribute("disabled");
+            $("#vOptionCenterSum")[0].removeAttribute("disabled");
+            $("#vOptionDownSum")[0].removeAttribute("disabled");
+            $("#rdIsText")[0].removeAttribute("disabled");
+            $("#rdIsField")[0].removeAttribute("disabled");
+            $("#eleIsNarrowSumEx")[0].removeAttribute("disabled");
         } else {
-            ctrl = textNode[JV.PROP_CONTROL];
+            $("#sumFieldControlDiv")[0].style.cursor = "not-allowed";
+            $("#hOptionLeftSum")[0].disabled = "disabled" ;
+            $("#hOptionCenterSum")[0].disabled = "disabled" ;
+            $("#hOptionRightSum")[0].disabled = "disabled" ;
+            $("#vOptionUpSum")[0].disabled = "disabled" ;
+            $("#vOptionCenterSum")[0].disabled = "disabled" ;
+            $("#vOptionDownSum")[0].disabled = "disabled" ;
+            $("#rdIsText")[0].disabled = "disabled" ;
+            $("#rdIsField")[0].disabled = "disabled" ;
+            $("#eleIsNarrowSumEx")[0].disabled = "disabled";
         }
-        if (ctrl) {
-            switch (ctrl.Horizon) {
-                case `center`:
-                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
-                    break;
-                case `right`:
-                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.right);
-                    break;
-                default:
-                    cell.hAlign(GC.Spread.Sheets.HorizontalAlign.left);
+    },
+    private_create_field_node: function (sheet, colWidthArr, rowHeightArr, text, rptTpl) {
+        let cellValue = text[`text`].toString().slice(1, -1);
+        let rst = {"Name": cellValue, "Title": '', "FieldID": -1, "font": "GrandTotal", "control": "Column_Right", "style" : "Default_Normal", "isAutoHeight" : false,
+            "area" : {"Left" : 0, "Right" : 100, "Top" : 0, "Bottom" : 100, "H_CalculationType" : "percentage", "V_CalculationType" : "percentage"}
+        };
+        //1. 设置FieldID
+        let hasChkField = false;
+        if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS] !== undefined && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS].length > 0) {
+            for (let field of rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]) {
+                if (field[JV.PROP_NAME] === cellValue) {
+                    rst.FieldID = field[JV.PROP_ID];
+                    rst["Title"] = "ID: " + field[JV.PROP_ID];
+                    hasChkField = true;
                     break;
+                }
             }
-            switch (ctrl.Vertical) {
-                case `center`:
-                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
-                    break;
-                case `bottom`:
-                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.bottom);
-                    break;
-                default:
-                    cell.vAlign(GC.Spread.Sheets.VerticalAlign.top);
+        }
+        if (!hasChkField && rptTpl[JV.NODE_NO_MAPPING_FIELDS] !== undefined && rptTpl[JV.NODE_NO_MAPPING_FIELDS].length > 0) {
+            for (let field of rptTpl[JV.NODE_NO_MAPPING_FIELDS]) {
+                if (field[JV.PROP_NAME] === cellValue) {
+                    rst.FieldID = field[JV.PROP_ID];
+                    rst["Title"] = "ID: " + field[JV.PROP_ID];
+                    hasChkField = true;
                     break;
+                }
             }
         }
-    },
-    private_setCellStyle: function (cell, textNode) {
-        //默认是normal,暂时不管
-    },
-    private_setCellFont: function (cell, textNode) {
-        for (let font of rpt_tpl_cfg_helper.reportCfg.fonts) {
-            if (font.ID === textNode[JV.PROP_FONT]) {
-                cell.font(Math.round(font[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]] * 3 / 4) + 'pt ' + font[JV.FONT_PROPS[JV.FONT_PROP_IDX_NAME]]);
-                break;
-            }
+        let cell = sheet.getCell(text.row, text.col);
+        //2. 字体
+        if (cell.font().indexOf('Narrow') > 0) {
+            rst[JV.PROP_FONT] = "Content_Narrow";
         }
+        //3. 上下左右位置
+        virtualCommonOprObj.setupHeightWidth(rst, text, colWidthArr, rowHeightArr);
+        return rst;
     },
 
     applySummaryBack: function () {
@@ -280,25 +370,45 @@ let virtualSummaryOprObj = {
             let rAmt = sheet.getRowCount(), pixH = [0];
             if (rAmt > 0) {
                 let texts = [], colWidthArr = [], rowHeightArr = [];
-                virtualCommonOprObj.collectSheetTxt(sheet, texts, colWidthArr, rowHeightArr);
-                for (let node of summaryParentNode.items) {
+                //1. 收集text信息
+                virtualCommonOprObj.collectSheetTxt(sheet, texts, 0, colWidthArr, rowHeightArr);
+                for (let node of me.summaryParentNode.items) {
                     dataInfoMapTreeOprObj.treeObj.removeChildNodes(node);
                 }
+                //2. 重新创建文本及统计指标
                 let txtNodes = [], fieldNodes = [];
                 for (let text of texts) {
                     if (!stringUtil.isEmptyString(text[`text`]) && text[`text`].indexOf(`{`) === 0) {
                         //创建指标
+                        fieldNodes.push(me.private_create_field_node(sheet, colWidthArr, rowHeightArr, text, rptTpl));
                     } else {
                         //创建文本
-                        let node = virtualCommonOprObj.createTxtNode(text, me.columnParentNode, colWidthArr, rowHeightArr);
-                        txtNodes.push(node);
+                        let textNode = virtualCommonOprObj.createTxtNode(text, me.columnParentNode, colWidthArr, rowHeightArr);
+                        let cell = sheet.getCell(text.row, text.col);
+                        if (cell.font().indexOf('Narrow') < 0) {
+                            textNode[JV.PROP_FONT] = "GrandTotal";
+                        } else {
+                            textNode[JV.PROP_FONT] = "Content_Narrow";
+                        }
+                        textNode[JV.PROP_CONTROL] = "Column";
+                        textNode[JV.PROP_STYLE] = "Default_Normal";
+                        txtNodes.push(textNode);
                     }
                 }
-                //....
-                let selectedBand = virtualCommonOprObj.getBandEx(summaryParentNode[JV.PROP_BAND_NAME], rptTpl);
-                selectedBand[JV.BAND_PROP_HEIGHT] = (rowHeightArr[rowHeightArr.length - 1] / 96 * 2.54).toFixed(2);
+                let fieldNode = me.summaryParentNode.items[0], textNode = me.summaryParentNode.items[1];
+                if (txtNodes.length > 0) {
+                    dataInfoMapTreeOprObj.treeObj.addNodes(textNode, -1, txtNodes, true);
+                }
+                if (fieldNodes.length > 0) {
+                    dataInfoMapTreeOprObj.treeObj.addNodes(fieldNode, -1, fieldNodes, true);
+                }
+                //3. 重新设置band高度
+                // let selectedBand = virtualCommonOprObj.getBandEx(me.summaryParentNode[JV.PROP_BAND_NAME], rptTpl);
+                // selectedBand[JV.BAND_PROP_HEIGHT] = (rowHeightArr[rowHeightArr.length - 1] / 96 * 2.54).toFixed(2);
+                virtualCommonOprObj.changeBandHeight(me.summaryParentNode[JV.PROP_BAND_NAME], (rowHeightArr[rowHeightArr.length - 1] / 96 * 2.54).toFixed(2));
+                displayMessage("应用提交成功!", "green", 5000, "id_summary_setup_lbl");
             } else {
-                displayMessage("模板行数量不足!", "red", 2000, "id_summary_setup_lbl");
+                displayMessage("模板行数量不足!", "red", 5000, "id_summary_setup_lbl");
             }
         }
     }