Browse Source

可视化建表 - v1.0

TonyKang 6 years ago
parent
commit
489c7b0f17

File diff suppressed because it is too large
+ 49 - 0
lib/font-zy/iconfont.css


BIN
lib/font-zy/iconfont.eot


File diff suppressed because it is too large
+ 74 - 0
lib/font-zy/iconfont.svg


BIN
lib/font-zy/iconfont.ttf


BIN
lib/font-zy/iconfont.woff


+ 1 - 1
web/maintain/report/html/rpt_tpl_dtl.html

@@ -12,7 +12,7 @@
         <li class="nav-item">
             <a class="nav-link p-1" data-toggle="tab" href="#rpttplfieldlocation" role="tab" onclick="dataInfoMapTreeOprObj.iniDataMap();">指标摆放</a>
         </li>
-        <li class="nav-item" style="display: none;">
+        <li class="nav-item" style="display: block;">
             <a class="nav-link p-1" data-toggle="tab" href="#rptvisual" role="tab" onclick="setTimeout(function(){visualJumbo.iniSpreadJs(); visualJumbo.setupTpl()}, 50)">可视化</a>
         </li>
         <li class="nav-item">

+ 8 - 8
web/maintain/report/html/rpt_tpl_dtl_vis_column.html

@@ -16,14 +16,14 @@
         <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="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="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>
+            <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="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>
                 <label style="display:none" class="form-check-label"><input type="checkbox" class="form-check-input" id="eleShowZeroEx" onchange="fieldLocationOprObj.changeCtrl(this)" disabled>显示0</label>

+ 1 - 0
web/maintain/report/html/rpt_tpl_main.html

@@ -13,6 +13,7 @@
     -->
     <link rel="stylesheet" href="/web/maintain/report/css/main.css">
     <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" href="/lib/font-zy/iconfont.css">
     <!--spread-->
     <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.sc.css">
     <!--zTree-->

+ 68 - 4
web/maintain/report/html/rpt_tpl_vis_jumbo.html

@@ -1,24 +1,88 @@
 <div class="tab-pane" id="rptvisual" role="tabpanel">
     <div class="main-data">
         <div class="p-3">
-            <button class="btn btn-primary btn-sm" onclick="">应用</button>
+            <button class="btn btn-primary btn-sm" onclick="visualJumbo.applyBack()">应用</button>
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.restoreTpl()">恢复</button>
+            &nbsp&nbsp&nbsp&nbsp
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.insertColumn()">插入列</button>
+            <div class="btn-group" role="group">
+                <button type="button" class="btn btn-outline-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">拆分</button>
+                <div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitColumn(2)">2列</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitColumn(3)">3列</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitColumn(4)">4列</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitColumn(5)">5列</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitColumn(10)">10列</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitColumn(20)">20列</a>
+                </div>
+            </div>
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.addColumn()">新增列</button>
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.deleteColumn()">删除列</button>
+            &nbsp&nbsp&nbsp&nbsp
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.addRow()">新增行</button>
+            <div class="btn-group" role="group" style="display: none">
+                <button type="button" class="btn btn-outline-primary btn-sm dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">拆分</button>
+                <div class="dropdown-menu" aria-labelledby="btnGroupDrop1">
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitRows(2)">2行</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitRows(3)">3行</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitRows(4)">4行</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitRows(5)">5行</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitRows(10)">10行</a>
+                    <a class="dropdown-item" style="cursor:pointer" onclick="visualJumbo.splitRows(20)">20行</a>
+                </div>
+            </div>
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.deleteRow()">删除行</button>
+            &nbsp&nbsp&nbsp&nbsp
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.mergeCells()">合并单元格</button>
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.disMergeCells()">拆解单元格</button>
+            &nbsp&nbsp&nbsp&nbsp
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.fitTheWidth(1.0)">X 1.0</button>
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.fitTheWidth(1.5)">X 1.5</button>
             <button class="btn btn-primary btn-sm" onclick="visualJumbo.fitTheWidth(2.0)">X 2.0</button>
-
-            <div class="row" id="ele_visual_div_cfg1">
+            <div style="height: 10px"></div>
+            <div>
+                <div class="row" id="ele_visual_div_cfg1">
+                    <div class="input-group col-2">
+                        <select class="form-control input-sm" id="visElementFonts" onchange="visualJumbo.changeFontSet(this)" disabled></select>
+                    </div>
+                    <div class="input-group col-1" disabled>
+                        <select class="form-control input-sm" id="visElementFontNames" onchange="visualJumbo.setupCellFont()" disabled><option>宋体</option><option>楷体</option><option>黑体</option></select>
+                    </div>
+                    <div class="form-group col-1">
+                        <input class="form-control input-sm" id="visEleFontSize" type="number" value="12" step="1" min="6" max="56" onchange="visualJumbo.setupCellFont()" disabled>
+                    </div>
+                    <div id= "font_other_properties_div" class="form-group col-2" style="display: none;">
+                        <a id="vis_font_bold" class="btn btn-sm btn-outline-secondary" title="加粗" onclick="visualJumbo.fontBoldChange(this)"><i class="fa fa-bold"></i></a>
+                        <a id="vis_font_italic" class="btn btn-sm btn-outline-secondary" title="斜体" onclick="visualJumbo.fontItalicChange(this)"><i class="fa fa-italic"></i></a>
+                        <a id="vis_font_underline" class="btn btn-sm btn-outline-secondary" title="下划线" onclick="visualJumbo.fontUnderlineChange(this)"><i class="fa fa-underline"></i></a>
+                    </div>
+                </div>
             </div>
             <div class="row" id="ele_visual_div_cfg2">
+                <div class="form-group col-md-12">
+                    <a id="hAlign_left" class="btn btn-sm btn-outline-secondary active" title="左对齐" onclick="visualJumbo.changeHAlign(this)"><i class="icon zyfont zy-ic_format_align_left"></i></a>
+                    <a id="hAlign_center" class="btn btn-sm btn-outline-secondary" title="水平中对齐" onclick="visualJumbo.changeHAlign(this)"><i class="icon zyfont zy-ic_format_align_center"></i></a>
+                    <a id="hAlign_right" class="btn btn-sm btn-outline-secondary" title="右对齐" onclick="visualJumbo.changeHAlign(this)"><i class="icon zyfont zy-ic_format_align_right"></i></a>
+                    &nbsp&nbsp&nbsp&nbsp
+                    <a id="vAlign_top" style="display: none" class="btn btn-sm btn-outline-secondary" title="上对齐" onclick="visualJumbo.changeVAlign(this)"><i class="icon zyfont zy-ic_vertical_align_top"></i></a>
+                    <a id="vAlign_center" class="btn btn-sm btn-outline-secondary active" title="垂直中对齐" onclick="visualJumbo.changeVAlign(this)"><i class="icon zyfont zy-ic_vertical_align_center"></i></a>
+                    <a id="vAlign_bottom" class="btn btn-sm btn-outline-secondary" title="下对齐" onclick="visualJumbo.changeVAlign(this)"><i class="icon zyfont zy-ic_vertical_align_bottom"></i></a>
+                    &nbsp&nbsp&nbsp&nbsp
+                    <a id="vis_shrink" class="btn btn-sm btn-outline-secondary" title="缩放" onclick="visualJumbo.changeShrink(this)" style="display: none"><i class="icon zyfont zy-ic_format_shapes"></i></a>
+                    <a id="vis_wrap" class="btn btn-sm btn-outline-secondary" title="折行" onclick="visualJumbo.changeWrap(this)" style="display: none"><i class="icon zyfont zy-ic_wrap_text"></i></a>
+                    &nbsp&nbsp&nbsp&nbsp
+                    <a id="vis_outter_border" class="btn btn-sm btn-outline-secondary" title="外边框" onclick="visualJumbo.changeBorder(this)"><i class="icon zyfont zy-ic_border_outer"></i></a>
+                    <a id="vis_no_border" class="btn btn-sm btn-outline-secondary" title="无边框" onclick="visualJumbo.changeBorder(this)"><i class="icon zyfont zy-ic_border_clear"></i></a>
+                    &nbsp&nbsp&nbsp&nbsp
+                    <label ><input type="radio" name="visCellTypes3" id="visRdIsText" onchange="visualJumbo.changeCellType(`text`)" checked="true" disabled>文本</label>
+                    <label ><input type="radio" name="visCellTypes3" id="visRdIsField" onchange="visualJumbo.changeCellType(`field`)" disabled>指标</label>
+                    <label ><input type="radio" name="visCellTypes3" id="visRdIsBlank" onchange="visualJumbo.changeCellType(`blank`)" disabled>空白</label>
+                    &nbsp&nbsp&nbsp&nbsp
+                    <label class="form-check-label" id="lblIsAutoHeightVis" style="display: none"><input type="checkbox" class="form-check-input" id="eleIsAutoHeightVis" onchange="visualJumbo.changeIsAutoHeight(this)">自动行高</label>
+                </div>
             </div>
-            <div class="row" style="height: 360px" id="ele_visual_div_main3">
+            <label id="id_vis_setup_lbl" style="color:green;font-weight:bold">...</label>
+            <div class="row p-3" style="height: 400px" id="ele_visual_div_main3">
             </div>
         </div>
     </div>

+ 2 - 0
web/maintain/report/js/rpt_tpl_cfg_helper.js

@@ -26,12 +26,14 @@ let rpt_tpl_cfg_helper = {
                 if (font.CfgDispName) {
                     me.reportCfg.fontArr.push(font.ID);
                     $("#elementFonts").append("<option value='" + font.ID + "'>" + font.CfgDispName + "</option>");
+                    $("#visElementFonts").append("<option value='" + font.ID + "'>" + font.CfgDispName + "</option>");
                 } else {
                     // me.reportCfg.fontArr.push("dummy font");
                 }
             }
             me.reportCfg.fontArr.push('自定义');
             $("#elementFonts").append("<option value='自定义'>自定义</option>");
+            $("#visElementFonts").append("<option value='自定义'>自定义</option>");
             me.reportCfg.controlArr = [];
             for (let control of me.reportCfg.ctrls) {
                 if (control.CfgDispName) {

+ 27 - 23
web/maintain/report/js/rpt_tpl_data_map.js

@@ -700,32 +700,36 @@ let dataInfoMapTreeOprObj = {
         let sumFieldObj = {};
         for (let subNode of grpNode.items) {
             if (subNode[JV.PROP_NAME] === "分组判断指标集") {
-                for (let sumField of subNode.items) {
-                    let item = {FieldID: sumField[JV.PROP_FIELD_ID]};
-                    rst[JV.PROP_GROUP_FIELDS].push(item);
+                if (subNode.items && subNode.items.length > 0) {
+                    for (let sumField of subNode.items) {
+                        let item = {FieldID: sumField[JV.PROP_FIELD_ID]};
+                        rst[JV.PROP_GROUP_FIELDS].push(item);
+                    }
                 }
             } else if (subNode[JV.PROP_NAME] === "分组行") {
-                for (let line of subNode.items) {
-                    let grpLine = {"SumKey_S": [], "text_s":[]};
-                    rst[JV.PROP_GROUP_LINES].push(grpLine);
-                    for (let dtl of line.items) {
-                        if (dtl[JV.PROP_NAME] === "分组字段集") {
-                            for (let gf of dtl.items) {
-                                if (!sumFieldObj[gf[JV.PROP_NAME]]) {
-                                    sumFieldObj[gf[JV.PROP_NAME]] = "Y";
-                                    rst[JV.PROP_SUM_FIELDS].push({"FieldID": gf[JV.PROP_FIELD_ID], "SumKey": gf[JV.PROP_NAME]});
+                if (subNode.items && subNode.items.length > 0) {
+                    for (let line of subNode.items) {
+                        let grpLine = {"SumKey_S": [], "text_s":[]};
+                        rst[JV.PROP_GROUP_LINES].push(grpLine);
+                        for (let dtl of line.items) {
+                            if (dtl[JV.PROP_NAME] === "分组字段集") {
+                                for (let gf of dtl.items) {
+                                    if (!sumFieldObj[gf[JV.PROP_NAME]]) {
+                                        sumFieldObj[gf[JV.PROP_NAME]] = "Y";
+                                        rst[JV.PROP_SUM_FIELDS].push({"FieldID": gf[JV.PROP_FIELD_ID], "SumKey": gf[JV.PROP_NAME]});
+                                    }
+                                    let item = {};
+                                    // rst[JV.PROP_SUM_FIELDS].push(item);
+                                    me.private_copy_field_properties(gf, item);
+                                    item[JV.PROP_SUM_KEY] = gf[JV.PROP_NAME];
+                                    grpLine[JV.PROP_GROUP_SUM_KEYS].push(item);
+                                }
+                            } else if (dtl[JV.PROP_NAME] === "文本集") {
+                                for (let txt of dtl.items) {
+                                    let item = {};
+                                    grpLine[JV.PROP_TEXTS].push(item);
+                                    me.private_copy_text_properties(txt, item);
                                 }
-                                let item = {};
-                                // rst[JV.PROP_SUM_FIELDS].push(item);
-                                me.private_copy_field_properties(gf, item);
-                                item[JV.PROP_SUM_KEY] = gf[JV.PROP_NAME];
-                                grpLine[JV.PROP_GROUP_SUM_KEYS].push(item);
-                            }
-                        } else if (dtl[JV.PROP_NAME] === "文本集") {
-                            for (let txt of dtl.items) {
-                                let item = {};
-                                grpLine[JV.PROP_TEXTS].push(item);
-                                me.private_copy_text_properties(txt, item);
                             }
                         }
                     }

+ 144 - 45
web/maintain/report/js/rpt_tpl_vis_common.js

@@ -172,7 +172,8 @@ let visualCommonOprObj = {
             case `field`:
                 let rptTpl = (zTreeOprObj.currentNode)?zTreeOprObj.currentNode.rptTpl:null;
                 let cellType = new GC.Spread.Sheets.CellTypes.ComboBox();
-                let selectableFields = me.getSelectedFields(rptTpl);
+                // let selectableFields = me.getSelectedFields(rptTpl);
+                let selectableFields = me.getAllSelectedFields(rptTpl);
                 cellType.items(selectableFields);
                 cell.cellType(cellType);
                 if (newColor) {
@@ -197,7 +198,10 @@ let visualCommonOprObj = {
         let me = this;
         me.private_setCellFont(cell, itemNode);
         me.private_setCellControl(cell, itemNode);
-        me.private_setCellStyle(cell, itemNode);
+        // let border = new GC.Spread.Sheets.LineBorder;
+        // border.color = "Black";
+        // border.style = GC.Spread.Sheets.LineStyle.thin;
+        // me.private_setCellStyle(cell, itemNode, border);
         let value = itemNode[JV.PROP_NAME];
         if (itemNode[JV.PROP_NAME].indexOf(`|`) >= 0) {
             value = itemNode[JV.PROP_NAME].split('|').join('\n');
@@ -238,8 +242,36 @@ let visualCommonOprObj = {
             }
         }
     },
-    private_setCellStyle: function (cell, textNode) {
-        //默认是normal,暂时不管
+    private_setCellStyle: function (cell, textNode, border) {
+        let style;
+        if (typeof textNode[JV.PROP_STYLE] === 'string') {
+            let idx = rpt_tpl_cfg_helper.reportCfg.borderArr.indexOf(textNode[JV.PROP_STYLE]);
+            style = rpt_tpl_cfg_helper.reportCfg.styles[idx];
+        } else {
+            style = textNode[JV.PROP_STYLE];
+        }
+        if (style) {
+            for (let borderStyle of style[JV.PROP_BORDER_STYLE]) {
+                if (parseFloat(borderStyle[JV.PROP_LINE_WEIGHT]) > 0) {
+                    switch (borderStyle[JV.PROP_POSITION]) {
+                        case JV.PROP_LEFT:
+                            cell.borderLeft(border);
+                            break;
+                        case JV.PROP_RIGHT:
+                            cell.borderRight(border);
+                            break;
+                        case JV.PROP_TOP:
+                            cell.borderTop(border);
+                            break;
+                        case JV.PROP_BOTTOM:
+                            cell.borderBottom(border);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            }
+        }
     },
     private_setCellFont: function (cell, textNode) {
         for (let font of rpt_tpl_cfg_helper.reportCfg.fonts) {
@@ -263,6 +295,30 @@ let visualCommonOprObj = {
         }
         return rst;
     },
+    getAllSelectedFields: 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]);
+            }
+        }
+        if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS] !== undefined && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS].length > 0) {
+            for (let field of rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS]) {
+                rst.push(field[JV.PROP_NAME]);
+            }
+        }
+        if (rptTpl[JV.NODE_DISCRETE_PARAMS] !== undefined && rptTpl[JV.NODE_DISCRETE_PARAMS].length > 0) {
+            for (let field of rptTpl[JV.NODE_DISCRETE_PARAMS]) {
+                rst.push(field[JV.PROP_NAME]);
+            }
+        }
+        return rst;
+    },
     setupCellDft: function (cell) {
         cell.font(`9pt 宋体`);
         cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
@@ -310,6 +366,7 @@ let visualCommonOprObj = {
             }
             let item = {};
             bandMappingObj[band[JV.PROP_NAME]] = item;
+            item[JV.PROP_BAND_NAME] = band[JV.PROP_NAME];
             item[JV.PROP_AREA] = {};
             item[JV.PROP_AREA][JV.PROP_LEFT] = left;
             item[JV.PROP_AREA][JV.PROP_RIGHT] = right;
@@ -372,7 +429,13 @@ let visualCommonOprObj = {
                     let bkBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
                     contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH;
                     lastContentBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
-                    me.addNormalTxtFldPos(contentBandMap, node, xPos, yPos);
+                    if (node.items.length === 0) {
+                        if (yPos.indexOf(contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH) < 0) {
+                            yPos.push(contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH);
+                        }
+                    } else {
+                        me.addNormalTxtFldPos(contentBandMap, node, xPos, yPos);
+                    }
                     contentBandMap[JV.PROP_AREA][JV.PROP_TOP] = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
                     contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = bkBottom;
                     contentBandMap[JV.PROP_COLOR] = 'LightCyan';
@@ -393,17 +456,19 @@ let visualCommonOprObj = {
                     if (contentBandMap && contentRowH && node.items && node.items.length > 0) {
                         for (let itemNode of node.items) {
                             if (itemNode[JV.PROP_NAME] === `分组行`) {
-                                for (let subItemNode of itemNode.items) {
-                                    //行
-                                    let bkBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
-                                    contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH;
-                                    lastContentBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
-                                    for (let txtFldNode of subItemNode.items) {
-                                        //分组字段集 与 文本集
-                                        me.addNormalTxtFldPos(contentBandMap, txtFldNode, xPos, yPos);
+                                if (itemNode.items) {
+                                    for (let subItemNode of itemNode.items) {
+                                        //行
+                                        let bkBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
+                                        contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH;
+                                        lastContentBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
+                                        for (let txtFldNode of subItemNode.items) {
+                                            //分组字段集 与 文本集
+                                            me.addNormalTxtFldPos(contentBandMap, txtFldNode, xPos, yPos);
+                                        }
+                                        contentBandMap[JV.PROP_AREA][JV.PROP_TOP] = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
+                                        contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = bkBottom;
                                     }
-                                    contentBandMap[JV.PROP_AREA][JV.PROP_TOP] = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
-                                    contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = bkBottom;
                                 }
                             }
                         }
@@ -436,6 +501,7 @@ let visualCommonOprObj = {
     },
     setupTplTxtFld: function (rptTpl, tree, sheet, xPos, yPos, bandMappingObj) {
         let me = this, nodes = tree.getNodes();
+        bandMappingObj.fontAttr = {};
         if (rptTpl[JV.NODE_FLOW_INFO]) {
             //流水式
             let contentBandMap, contentRowH;
@@ -444,7 +510,7 @@ let visualCommonOprObj = {
                     //1. 列
                     let bandMap = bandMappingObj[node[JV.PROP_BAND_NAME]];
                     // me.addNormalTxtFldPos(bandMap, node, xPos, yPos);
-                    me.addSpanWholeArea(bandMap, node, sheet, xPos, yPos);
+                    me.addSpanWholeArea(bandMappingObj, bandMap, node, sheet, xPos, yPos);
                 } else if (node[JV.PROP_NAME].indexOf('数据') >= 0) {
                     //2. 数据
                     contentBandMap = bandMappingObj[node[JV.PROP_BAND_NAME]];
@@ -452,7 +518,7 @@ let visualCommonOprObj = {
                     let bkBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
                     contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH;
                     // me.addNormalTxtFldPos(contentBandMap, node, xPos, yPos);
-                    me.addSpanWholeArea(contentBandMap, node, sheet, xPos, yPos);
+                    me.addSpanWholeArea(bandMappingObj, contentBandMap, node, sheet, xPos, yPos);
                     contentBandMap[JV.PROP_AREA][JV.PROP_TOP] = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
                     contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = bkBottom;
                 } else if (node[JV.PROP_NAME].indexOf('_页统计') >= 0) {
@@ -460,31 +526,33 @@ let visualCommonOprObj = {
                     let bandMap = bandMappingObj[node[JV.PROP_BAND_NAME]];
                     for (let itemNode of node.items) {
                         // me.addNormalTxtFldPos(bandMap, itemNode, xPos, yPos);
-                        me.addSpanWholeArea(bandMap, itemNode, sheet, xPos, yPos);
+                        me.addSpanWholeArea(bandMappingObj, bandMap, itemNode, sheet, xPos, yPos);
                     }
                 } else if (node[JV.PROP_NAME].indexOf('_段统计') >= 0) {
                     //4. 章统计
                     let bandMap = bandMappingObj[node[JV.PROP_BAND_NAME]];
                     for (let itemNode of node.items) {
                         // me.addNormalTxtFldPos(bandMap, itemNode, xPos, yPos);
-                        me.addSpanWholeArea(bandMap, itemNode, sheet, xPos, yPos);
+                        me.addSpanWholeArea(bandMappingObj, bandMap, itemNode, sheet, xPos, yPos);
                     }
                 } else if (node[JV.PROP_NAME].indexOf('_分组') >= 0) {
                     //5. 分组统计
                     if (contentBandMap && contentRowH && node.items && node.items.length > 0) {
                         for (let itemNode of node.items) {
                             if (itemNode[JV.PROP_NAME] === `分组行`) {
-                                for (let subItemNode of itemNode.items) {
-                                    //行
-                                    let bkBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
-                                    contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH;
-                                    for (let txtFldNode of subItemNode.items) {
-                                        //分组字段集 与 文本集
-                                        // me.addNormalTxtFldPos(contentBandMap, txtFldNode, xPos, yPos);
-                                        me.addSpanWholeArea(contentBandMap, txtFldNode, sheet, xPos, yPos);
+                                if (itemNode.items) {
+                                    for (let subItemNode of itemNode.items) {
+                                        //行
+                                        let bkBottom = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
+                                        contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = contentBandMap[JV.PROP_AREA][JV.PROP_TOP] + contentRowH;
+                                        for (let txtFldNode of subItemNode.items) {
+                                            //分组字段集 与 文本集
+                                            // me.addNormalTxtFldPos(contentBandMap, txtFldNode, xPos, yPos);
+                                            me.addSpanWholeArea(bandMappingObj, contentBandMap, txtFldNode, sheet, xPos, yPos);
+                                        }
+                                        contentBandMap[JV.PROP_AREA][JV.PROP_TOP] = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
+                                        contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = bkBottom;
                                     }
-                                    contentBandMap[JV.PROP_AREA][JV.PROP_TOP] = contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM];
-                                    contentBandMap[JV.PROP_AREA][JV.PROP_BOTTOM] = bkBottom;
                                 }
                             }
                         }
@@ -501,7 +569,7 @@ let visualCommonOprObj = {
                 if (node[JV.PROP_NAME].indexOf('数据') >= 0) {
                     //1. 数据
                     let bandMap = bandMappingObj[node[JV.PROP_BAND_NAME]];
-                    me.addSpanWholeArea(bandMap, node, sheet, xPos, yPos);
+                    me.addSpanWholeArea(bandMappingObj, bandMap, node, sheet, xPos, yPos);
                 } else if (node[JV.PROP_NAME].indexOf('离散') >= 0) {
                     //2. 离散信息
                     me.addDiscreteSpan(node, xPos, yPos, bandMappingObj, sheet);
@@ -529,13 +597,15 @@ let visualCommonOprObj = {
     },
     addDiscreteTxtFldPos: function (discreteItemNode, xPos, yPos, bandMappingObj) {
         let me = this;
-        for (let itemNode of discreteItemNode.items) {
-            //子项
-            let bandMap = bandMappingObj[itemNode[JV.PROP_BAND_NAME]];
-            if (bandMap) {
-                for (let subItemNode of itemNode.items) {
-                    for (let txtFldDtlNode of subItemNode.items) {
-                        me.pushAbsPos(bandMap, txtFldDtlNode, xPos, yPos);
+        if (discreteItemNode.items) {
+            for (let itemNode of discreteItemNode.items) {
+                //子项
+                let bandMap = bandMappingObj[itemNode[JV.PROP_BAND_NAME]];
+                if (bandMap) {
+                    for (let subItemNode of itemNode.items) {
+                        for (let txtFldDtlNode of subItemNode.items) {
+                            me.pushAbsPos(bandMap, txtFldDtlNode, xPos, yPos);
+                        }
                     }
                 }
             }
@@ -549,7 +619,7 @@ let visualCommonOprObj = {
             }
         }
     },
-    addSpanWholeArea: function (bandMap, parentNode, sheet, xPos, yPos) {
+    addSpanWholeArea: function (bandMappingObj, bandMap, parentNode, sheet, xPos, yPos) {
         let me = this;
         if (bandMap && parentNode.items && parentNode.items.length > 0) {
             let bandW = bandMap[JV.PROP_AREA][JV.PROP_RIGHT] - bandMap[JV.PROP_AREA][JV.PROP_LEFT],
@@ -569,23 +639,41 @@ let visualCommonOprObj = {
                     sheet.addSpan(idxTop, idxLeft, idxBottom - idxTop, idxRight - idxLeft, GC.Spread.Sheets.SheetArea.viewport);
                 }
                 let cell = sheet.getCell(idxTop, idxLeft, GC.Spread.Sheets.SheetArea.viewport);
-                if (itemNode.FieldID) {
+                if (itemNode.FieldID || itemNode.ParamID) {
                     me.changeCellType(cell, 'field', bandMap[JV.PROP_COLOR]);
                 } else {
                     me.changeCellType(cell, 'text', bandMap[JV.PROP_COLOR]);
                 }
+                bandMappingObj.fontAttr[idxTop + "_" + idxLeft + "_font"] = itemNode[JV.PROP_FONT];
                 me.setupCell(cell, itemNode);
+                if ((itemNode.FieldID || itemNode.ParamID) && itemNode[JV.PROP_IS_AUTO_HEIGHT]) {
+                    let value = cell.value();
+                    cell.value(`{` + value + `}`);
+                }
+                //*
+                let border = new GC.Spread.Sheets.LineBorder;
+                border.color = "Black";
+                border.style = GC.Spread.Sheets.LineStyle.thin;
+                for (let iRow = 0; iRow < idxBottom - idxTop; iRow++) {
+                    for (let iCol = 0; iCol < idxRight - idxLeft; iCol++) {
+                        let cl = sheet.getCell(iRow + idxTop, iCol + idxLeft, GC.Spread.Sheets.SheetArea.viewport);
+                        me.private_setCellStyle(cl, itemNode, border);
+                    }
+                }
+                //*/
             }
         }
     },
     addDiscreteSpan: function (discreteItemNode, xPos, yPos, bandMappingObj, sheet) {
         let me = this;
-        for (let itemNode of discreteItemNode.items) {
-            //子项
-            let bandMap = bandMappingObj[itemNode[JV.PROP_BAND_NAME]];
-            if (bandMap) {
-                for (let subItemNode of itemNode.items) {
-                    me.addSpanWholeArea(bandMap, subItemNode, sheet, xPos, yPos);
+        if (discreteItemNode.items) {
+            for (let itemNode of discreteItemNode.items) {
+                //子项
+                let bandMap = bandMappingObj[itemNode[JV.PROP_BAND_NAME]];
+                if (bandMap) {
+                    for (let subItemNode of itemNode.items) {
+                        me.addSpanWholeArea(bandMappingObj, bandMap, subItemNode, sheet, xPos, yPos);
+                    }
                 }
             }
         }
@@ -595,5 +683,16 @@ let visualCommonOprObj = {
         cell.borderRight(border);
         cell.borderTop(border);
         cell.borderBottom(border);
+    },
+    copyPropertiesForSplittedCell: function (srcCell, destCell) {
+        //1. font
+        destCell.font(srcCell.font());
+        //2. bk color
+        destCell.backColor(srcCell.backColor());
+        //3. border
+        destCell.borderLeft(srcCell.borderLeft());
+        destCell.borderRight(srcCell.borderRight());
+        destCell.borderTop(srcCell.borderTop());
+        destCell.borderBottom(srcCell.borderBottom());
     }
 };

+ 909 - 16
web/maintain/report/js/rpt_tpl_vis_jumbo.js

@@ -4,21 +4,9 @@
 
 let visualJumbo = {
     tplWorkBook: null,
+    bandMappingObj: null,
     iniSpreadJs: function () {
         let me = this;
-        /*/
-        if (me.tplWorkBook === null) {
-            me.tplWorkBook = new GC.Spread.Sheets.Workbook($('#ele_visual_div_main3')[0], {sheetCount: 1});
-            me.tplWorkBook.options.tabStripVisible = false;
-            me.tplWorkBook.options.allowCopyPasteExcelStyle = false;
-            me.tplWorkBook.options.allowUserDragDrop = false;
-            me.tplWorkBook.options.allowContextMenu = false;
-            let sheet = me.tplWorkBook.getActiveSheet();
-            sheet.options.allowCellOverflow = false;
-            sheet.setRowCount(10, GC.Spread.Sheets.SheetArea.viewport);
-            // sheet.bind(GC.Spread.Sheets.Events.EnterCell, me.onCellEnter);
-        }
-        /*/
         if (me.tplWorkBook !== null) {
             me.tplWorkBook.destroy();
             me.tplWorkBook = null;
@@ -31,8 +19,7 @@ let visualJumbo = {
         let sheet = me.tplWorkBook.getActiveSheet();
         sheet.options.allowCellOverflow = false;
         sheet.options.clipBoardOptions = GC.Spread.Sheets.ClipboardPasteOptions.values;
-        // sheet.bind(GC.Spread.Sheets.Events.CellClick, me.onCellEnter);
-        //*/
+        sheet.bind(GC.Spread.Sheets.Events.CellClick, me.onCellEnter);
     },
     setupTpl: function () {
         let me = this;
@@ -49,6 +36,7 @@ let visualJumbo = {
             let xPos = [0], yPos = [0];
             let pageH, pageW;
             let bandMappingObj = {};
+            me.bandMappingObj = bandMappingObj;
             let pIdx = JV.PAGES_SIZE_STR.indexOf(rptTpl[JV.NODE_MAIN_INFO][JV.NODE_PAGE_INFO][JV.PROP_PAGE_SIZE]);
             pageW = Math.round(JV.PAGES_SIZE[pIdx][0] * 96 - (parseFloat(rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_LEFT]) + parseFloat(rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_RIGHT])) /2.54*96 );
             pageH = Math.round(JV.PAGES_SIZE[pIdx][1] * 96 - (parseFloat(rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_TOP]) + parseFloat(rptTpl[JV.NODE_MAIN_INFO][JV.NODE_MARGINS][JV.PROP_BOTTOM])) /2.54*96 );
@@ -87,6 +75,9 @@ let visualJumbo = {
                     let cell = sheet.getCell(iRow, iCol);
                     if (cell.backColor() === 'LightGray' || cell.backColor() === 'LightCyan') {
                         visualCommonOprObj.setupBorder(sheet.getCell(iRow, iCol), border);
+                    } else if (cell.backColor() === 'White') {
+                        sheet.addSpan(iRow, 0, 1, sheet.getColumnCount());
+                        break;
                     }
                 }
             }
@@ -94,12 +85,123 @@ let visualJumbo = {
             sheet.resumePaint();
         }
     },
+    onCellEnter: function (sender, args) {
+        let me = visualJumbo,
+            sheet = me.tplWorkBook.getActiveSheet();
+        me.setupCfg(sheet, args.row, args.col);
+    },
+    setupCfg: function (sheet, row, col) {
+        let me = visualJumbo,
+            cell = sheet.getCell(row, col);
+        if (cell.backColor() !== 'White') {
+            //0. 设置UI
+            $(`#visElementFonts`)[0].removeAttribute("disabled");
+            $(`#visRdIsText`)[0].removeAttribute("disabled");
+            $(`#visRdIsField`)[0].removeAttribute("disabled");
+            $(`#eleIsAutoHeightVis`)[0].removeAttribute("disabled");
+            $(`#font_other_properties_div`)[0].style.display = "none";
+            me.private_ShowBandName(cell);
+            //1. font
+            let fontAttr = me.bandMappingObj.fontAttr[row + "_" + col + "_font"];
+            if (fontAttr) {
+                me.private_setup_font(fontAttr);
+            }
+            //2. alignment
+            switch (cell.hAlign()) {
+                case GC.Spread.Sheets.HorizontalAlign.center:
+                    $(`#hAlign_left`)[0].className = "btn btn-sm btn-outline-secondary";
+                    $(`#hAlign_center`)[0].className = "btn btn-sm btn-outline-secondary active";
+                    $(`#hAlign_right`)[0].className = "btn btn-sm btn-outline-secondary";
+                    break;
+                case GC.Spread.Sheets.HorizontalAlign.right:
+                    $(`#hAlign_left`)[0].className = "btn btn-sm btn-outline-secondary";
+                    $(`#hAlign_center`)[0].className = "btn btn-sm btn-outline-secondary";
+                    $(`#hAlign_right`)[0].className = "btn btn-sm btn-outline-secondary active";
+                    break;
+                case GC.Spread.Sheets.HorizontalAlign.left:
+                default:
+                    $(`#hAlign_left`)[0].className = "btn btn-sm btn-outline-secondary active";
+                    $(`#hAlign_center`)[0].className = "btn btn-sm btn-outline-secondary";
+                    $(`#hAlign_right`)[0].className = "btn btn-sm btn-outline-secondary";
+                    break;
+            }
+            switch (cell.vAlign()) {
+                case GC.Spread.Sheets.VerticalAlign.bottom:
+                    $(`#vAlign_center`)[0].className = "btn btn-sm btn-outline-secondary";
+                    $(`#vAlign_bottom`)[0].className = "btn btn-sm btn-outline-secondary active";
+                    break;
+                case GC.Spread.Sheets.VerticalAlign.center:
+                default:
+                    $(`#vAlign_center`)[0].className = "btn btn-sm btn-outline-secondary active";
+                    $(`#vAlign_bottom`)[0].className = "btn btn-sm btn-outline-secondary";
+                    break;
+            }
+            //3. other control
+            if (cell.shrinkToFit()) {
+                $(`#vis_shrink`)[0].className = "btn btn-sm btn-outline-secondary active";
+            } else {
+                $(`#vis_shrink`)[0].className = "btn btn-sm btn-outline-secondary";
+            }
+            if (cell.wordWrap()) {
+                $(`#vis_wrap`)[0].className = "btn btn-sm btn-outline-secondary active";
+            } else {
+                $(`#vis_wrap`)[0].className = "btn btn-sm btn-outline-secondary";
+            }
+            let border = cell.borderLeft();
+            if (border && border.style === GC.Spread.Sheets.LineStyle.thin) {
+                $(`#vis_outter_border`)[0].className = "btn btn-sm btn-outline-secondary active";
+                $(`#vis_no_border`)[0].className = "btn btn-sm btn-outline-secondary";
+            } else {
+                $(`#vis_outter_border`)[0].className = "btn btn-sm btn-outline-secondary";
+                $(`#vis_no_border`)[0].className = "btn btn-sm btn-outline-secondary active";
+            }
+            //4. txt/field
+            let val = cell.value();
+            if (cell.cellType() && cell.cellType().typeName === '7') {
+                $(`#visRdIsField`)[0].checked = true;
+                $(`#lblIsAutoHeightVis`)[0].style.display = "";
+                if (!stringUtil.isEmptyString(val) && val.indexOf(`{`) === 0) {
+                    $(`#eleIsAutoHeightVis`)[0].checked = true;
+                } else {
+                    $(`#eleIsAutoHeightVis`)[0].checked = false;
+                }
+            } else if (stringUtil.isEmptyString(val) && (!border || border.style === GC.Spread.Sheets.LineStyle.empty)) {
+                $(`#visRdIsBlank`)[0].checked = true;
+                $(`#lblIsAutoHeightVis`)[0].style.display = "none";
+            } else {
+                $(`#visRdIsText`)[0].checked = true;
+                $(`#lblIsAutoHeightVis`)[0].style.display = "none";
+            }
+        } else {
+            $("#visElementFonts")[0].disabled = "disabled" ;
+            $("#visRdIsText")[0].disabled = "disabled" ;
+            $("#visRdIsField")[0].disabled = "disabled" ;
+            $("#eleIsAutoHeightVis")[0].disabled = "disabled" ;
+            $("#id_vis_setup_lbl")[0].innerHTML = '...';
+        }
+    },
     restoreTpl: function () {
         let me = visualJumbo;
         if (me.tplWorkBook) {
             me.setupTpl();
         }
     },
+    private_ShowBandName: function (cell) {
+        let me = visualJumbo;
+        if (me.bandMappingObj) {
+            let color = cell.backColor();
+            if (color && color !== 'White') {
+                for (let bItem of me.bandMappingObj.items) {
+                    if (bItem[JV.PROP_COLOR] === color) {
+                        $("#id_vis_setup_lbl")[0].innerHTML = bItem[JV.PROP_BAND_NAME];
+                        break;
+                    }
+                }
+            } else {
+                $("#id_vis_setup_lbl")[0].innerHTML = '...';
+            }
+        }
+    },
     private_AddCols: function (sheet, col) {
         sheet.suspendPaint();
         sheet.addColumns(col, 1);
@@ -118,6 +220,36 @@ let visualJumbo = {
             sheet = me.tplWorkBook.getActiveSheet();
         me.private_AddCols(sheet, sheet.getColumnCount());
     },
+    splitColumn: function (newColAmt) {
+        let me = visualJumbo,
+            sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            if (selectedRanges[0].colCount <= newColAmt) {
+                let width = 0;
+                for (let iCol = 0; iCol < selectedRanges[0].colCount; iCol++) {
+                    width += sheet.getColumnWidth(selectedRanges[0].col + iCol);
+                }
+                let avgW = Math.round(width / newColAmt),
+                    lastW = width - avgW * (newColAmt - 1);
+                sheet.suspendPaint();
+                sheet.addColumns(selectedRanges[0].col + selectedRanges[0].colCount, newColAmt - selectedRanges[0].colCount);
+                sheet.setColumnWidth(selectedRanges[0].col, lastW);
+                for (let iCol = 1; iCol < newColAmt; iCol++) {
+                    sheet.setColumnWidth(selectedRanges[0].col + iCol, avgW);
+                }
+                for (let iRow = 0; iRow < sheet.getRowCount(); iRow++) {
+                    let cell = sheet.getCell(iRow, selectedRanges[0].col);
+                    for (let iCol = selectedRanges[0].colCount; iCol < newColAmt; iCol++) {
+                        visualCommonOprObj.copyPropertiesForSplittedCell(cell, sheet.getCell(iRow, iCol + selectedRanges[0].col));
+                    }
+                }
+                sheet.resumePaint();
+            } else {
+                alert(`您选择的列数量比要拆分的数量还大!`);
+            }
+        }
+    },
     deleteColumn: function () {
         let me = visualJumbo,
             sheet = me.tplWorkBook.getActiveSheet();
@@ -153,6 +285,48 @@ let visualJumbo = {
             }
         }
     },
+    splitRows: function (newRowAmt) {
+        let me = visualJumbo,
+            sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            let firstCell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            let isSameBand = true;
+            for (let iRow = 1; iRow < selectedRanges[0].rowCount; i++) {
+                if (sheet.getCell(iRow + selectedRanges[0].row, 0).backColor() !== firstCell.backColor()) {
+                    isSameBand = false;
+                    break;
+                }
+            }
+            if (isSameBand) {
+                if (firstCell.backColor() !== 'White') {
+                    if (selectedRanges[0].rowCount <= newRowAmt) {
+                        let height = 0;
+                        for (let iRow = 0; iRow < selectedRanges[0].rowCount; iRow++) {
+                            height += sheet.getRowHeight(selectedRanges[0].row + iRow);
+                        }
+                        let avgH = Math.round(height / newRowAmt),
+                            lastH = height - avgH * (newRowAmt - 1);
+                        sheet.addRows(selectedRanges[0].row + selectedRanges[0].rowCount, newRowAmt - selectedRanges[0].rowCount);
+                        sheet.setRowHeight(selectedRanges[0].row, lastH);
+                        for (let iRow = 1; iRow < newRowAmt; iRow++) {
+                            sheet.setRowHeight(selectedRanges[0].row + iRow, avgH);
+                        }
+                        for (let iRow = selectedRanges[0].rowCount; iRow < newRowAmt; iRow++) {
+                            let cell = sheet.getCell(selectedRanges[0].row, 0);
+                            for (let iCol = 0; iCol < sheet.getColumnCount(); iCol++) {
+                                visualCommonOprObj.copyPropertiesForSplittedCell(cell, sheet.getCell(iRow + selectedRanges[0].row, iCol));
+                            }
+                        }
+                    } else {
+                        alert(`您选择的行数量比要拆分的数量还大!`);
+                    }
+                }
+            } else {
+                alert(`不能拆分跨界行!`);
+            }
+        }
+    },
     deleteRow: function () {
         let me = visualJumbo,
             sheet = me.tplWorkBook.getActiveSheet();
@@ -240,6 +414,725 @@ let visualJumbo = {
                 sheet.removeSpan(span.row, span.col, GC.Spread.Sheets.SheetArea.viewport);
             }
         }
-    }
+    },
+    changeFontSet: function (dom) {
+        let me = visualJumbo, fontAttr = dom.value,
+            sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            if (fontAttr === "自定义") {
+                fontAttr = {};
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_NAME]] = "宋体";
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]] = 12;
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_COLOR]] = "BLACK";
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_BOLD]] = "F"; //bold
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_ITALIC]] = "F"; //italic
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_UNDERLINE]] = "F"; //underline
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_STRIKEOUT]] = "F"; //strikeout
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_ANGLE]] = 0;   //angle
+            }
+            me.bandMappingObj.fontAttr[selectedRanges[0].row + "_" + selectedRanges[0].col + "_font"] = fontAttr;
+            me.private_setup_font(fontAttr);
+            if (typeof fontAttr === 'string') {
+                let idx = rpt_tpl_cfg_helper.reportCfg.fontArr.indexOf(fontAttr);
+                fontAttr = rpt_tpl_cfg_helper.reportCfg.fonts[idx];
+            }
+            me.private_setup_cell_font(cell, fontAttr);
+        }
+    },
+    setupCellFont: function () {
+        let me = visualJumbo, sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            let fontAttr = $(`#visElementFonts`)[0].value;
+            if (fontAttr === "自定义") {
+                fontAttr = {};
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_NAME]] = $(`#visElementFontNames`)[0].value;
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]] = $(`#visEleFontSize`)[0].value;
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_BOLD]] = ($("#vis_font_bold")[0].className === "btn btn-sm btn-outline-secondary")?'F':'T'; //bold
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_ITALIC]] = ($("#vis_font_italic")[0].className === "btn btn-sm btn-outline-secondary")?'F':'T'; //italic
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_UNDERLINE]] = ($("#vis_font_underline")[0].className === "btn btn-sm btn-outline-secondary")?'F':'T'; //underline
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_STRIKEOUT]] = "F"; //strikeout
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_COLOR]] = "BLACK";
+                fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_ANGLE]] = 0;   //angle
+                me.bandMappingObj.fontAttr[selectedRanges[0].row + "_" + selectedRanges[0].col + "_font"] = fontAttr;
+            } else {
+                let idx = rpt_tpl_cfg_helper.reportCfg.fontArr.indexOf(fontAttr);
+                fontAttr = rpt_tpl_cfg_helper.reportCfg.fonts[idx];
+                me.bandMappingObj.fontAttr[selectedRanges[0].row + "_" + selectedRanges[0].col + "_font"] = fontAttr;
+            }
+            let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            sheet.suspendPaint();
+            me.private_setup_cell_font(cell, fontAttr);
+            sheet.resumePaint();
+        }
+    },
+    setupCellAlignment: function () {
+        let me = visualJumbo, sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            // let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            sheet.suspendPaint();
+            for (let iRow = 0; iRow < selectedRanges[0].rowCount; iRow++) {
+                for (let iCol = 0; iCol < selectedRanges[0].colCount; iCol++) {
+                    let cell = sheet.getCell(selectedRanges[0].row + iRow, selectedRanges[0].col + iCol);
+                    //1. horizon alignment
+                    if ($(`#hAlign_center`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.center);
+                    } else if ($(`#hAlign_left`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.left);
+                    } else if ($(`#hAlign_right`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                        cell.hAlign(GC.Spread.Sheets.HorizontalAlign.right);
+                    }
+                    //2. vertical alignment
+                    if ($(`#vAlign_center`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                        cell.vAlign(GC.Spread.Sheets.VerticalAlign.center);
+                    } else if ($(`#vAlign_bottom`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                        cell.vAlign(GC.Spread.Sheets.VerticalAlign.bottom);
+                    }
+                    //3. shrink
+                    if ($(`#vis_shrink`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                        cell.shrinkToFit(true);
+                    } else {
+                        cell.shrinkToFit(false);
+                    }
+                    //4. wrap
+                    if ($(`#vis_wrap`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                        cell.wordWrap(true);
+                    } else {
+                        cell.wordWrap(false);
+                    }
+                }
+            }
+            sheet.resumePaint();
+        }
+    },
+    setupCellBorder: function () {
+        let me = visualJumbo, sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            // let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            sheet.suspendPaint();
+            let border = new GC.Spread.Sheets.LineBorder;
+            border.color = "Black";
+            if ($(`#vis_outter_border`)[0].className === `btn btn-sm btn-outline-secondary active`) {
+                border.style = GC.Spread.Sheets.LineStyle.thin;
+            } else {
+                border.style = GC.Spread.Sheets.LineStyle.empty;
+            }
+            let cellRange = new GC.Spread.Sheets.CellRange(sheet, selectedRanges[0].row, selectedRanges[0].col, selectedRanges[0].rowCount, selectedRanges[0].colCount);
+            cellRange.setBorder(border, {all: true});
+            sheet.resumePaint();
+        }
+    },
+    private_setup_cell_font: function (cell, fontAttr) {
+        let fontStr = "";
+        if (stringUtil.convertStrToBoolean(fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_BOLD]])) {
+            fontStr = 'bold ' + fontStr;
+        }
+        if (stringUtil.convertStrToBoolean(fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_ITALIC]])) {
+            fontStr = 'italic ' + fontStr;
+        }
+        fontStr = fontStr + Math.round(fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_HEIGHT]] * 3 / 4) + 'pt ' + fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_NAME]];
+        if (stringUtil.convertStrToBoolean(fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_UNDERLINE]])) {
+            cell.textDecoration(GC.Spread.Sheets.TextDecorationType.underline);
+        } else {
+            cell.textDecoration(GC.Spread.Sheets.TextDecorationType.none);
+        }
+        cell.font(fontStr);
+    },
+    private_setup_font: function(fontAttr) {
+        if (typeof fontAttr === "string" && fontAttr !== "自定义") {
+            $("#visElementFontNames")[0].disabled = "disabled" ;
+            $("#visEleFontSize")[0].disabled = "disabled" ;
+            let idx = rpt_tpl_cfg_helper.reportCfg.fontArr.indexOf(fontAttr);
+            let font = rpt_tpl_cfg_helper.reportCfg.fonts[idx];
+            $("#visElementFonts")[0].selectedIndex = idx;
+            $("#visElementFontNames")[0].value = font.Name;
+            $("#visEleFontSize")[0].value = parseInt(font.FontHeight);
 
+            $("#font_other_properties_div")[0].style.display = "none";
+            $("#vis_font_bold")[0].className = "btn btn-sm btn-outline-secondary";
+            $("#vis_font_italic")[0].className = "btn btn-sm btn-outline-secondary";
+            $("#vis_font_underline")[0].className = "btn btn-sm btn-outline-secondary";
+        } else {
+            $("#visElementFontNames")[0].removeAttribute("disabled");
+            $("#visEleFontSize")[0].removeAttribute("disabled");
+            $("#font_other_properties_div")[0].style.display = "";
+            $("#visElementFonts")[0].value = "自定义";
+            $("#visElementFontNames")[0].value = fontAttr.Name;
+            $("#visEleFontSize")[0].value = parseInt(fontAttr.FontHeight);
+            if (stringUtil.convertStrToBoolean(fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_BOLD]])) {
+                $("#vis_font_bold")[0].className = "btn btn-sm btn-outline-secondary active";
+            }
+            if (stringUtil.convertStrToBoolean(fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_ITALIC]])) {
+                $("#vis_font_italic")[0].className = "btn btn-sm btn-outline-secondary active";
+            }
+            if (stringUtil.convertStrToBoolean(fontAttr[JV.FONT_PROPS[JV.FONT_PROP_IDX_UNDERLINE]])) {
+                $("#vis_font_underline")[0].className = "btn btn-sm btn-outline-secondary active";
+            }
+        }
+    },
+    fontBoldChange: function (dom) {
+        let me = this;
+        me.private_reverse_class(dom);
+        me.setupCellFont();
+    },
+    fontItalicChange: function (dom) {
+        let me = this;
+        me.private_reverse_class(dom);
+        me.setupCellFont();
+    },
+    fontUnderlineChange: function (dom) {
+        let me = this;
+        me.private_reverse_class(dom);
+        me.setupCellFont();
+    },
+    changeShrink: function (dom) {
+        let me = this;
+        me.private_reverse_class(dom);
+        me.setupCellAlignment();
+    },
+    changeWrap: function (dom) {
+        let me = this;
+        me.private_reverse_class(dom);
+        me.setupCellAlignment();
+    },
+    changeIsAutoHeight: function (dom) {
+        let me = visualJumbo, sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            if (cell.cellType() && cell.cellType().typeName === '7') {
+                sheet.suspendPaint();
+                let val = cell.value();
+                if (dom.checked) {
+                    if (val.indexOf(`{`) < 0) {
+                        cell.value(`{` + val + `}`);
+                    }
+                } else {
+                    if (val.indexOf(`{`) === 0) {
+                        cell.value(val.replace('{', '').replace('}',''));
+                    }
+                }
+                sheet.resumePaint();
+            }
+        }
+    },
+    private_reverse_class: function (dom) {
+        if (dom.className === "btn btn-sm btn-outline-secondary") {
+            dom.className = "btn btn-sm btn-outline-secondary active";
+        } else {
+            dom.className = "btn btn-sm btn-outline-secondary";
+        }
+    },
+    changeHAlign: function (dom) {
+        let me = this;
+        if (dom.className === "btn btn-sm btn-outline-secondary") {
+            dom.className = "btn btn-sm btn-outline-secondary active"
+            let hKeys = [`hAlign_left`, `hAlign_center`, `hAlign_right`];
+            let domIdx = hKeys.indexOf(dom.id);
+            if (domIdx >= 0) {
+                for (let idx = 0; idx < hKeys.length; idx++) {
+                    if (idx !== domIdx) {
+                        $(`#` + hKeys[idx])[0].className = "btn btn-sm btn-outline-secondary";
+                    }
+                }
+            }
+            me.setupCellAlignment();
+        }
+    },
+    changeVAlign: function (dom) {
+        let me = this;
+        if (dom.className === "btn btn-sm btn-outline-secondary") {
+            dom.className = "btn btn-sm btn-outline-secondary active"
+            let hKeys = [`vAlign_top`, `vAlign_center`, `vAlign_bottom`];
+            let domIdx = hKeys.indexOf(dom.id);
+            if (domIdx >= 0) {
+                for (let idx = 0; idx < hKeys.length; idx++) {
+                    if (idx !== domIdx) {
+                        $(`#` + hKeys[idx])[0].className = "btn btn-sm btn-outline-secondary";
+                    }
+                }
+            }
+            me.setupCellAlignment();
+        }
+    },
+    changeBorder: function (dom) {
+        let me = this;
+        if (dom.className === "btn btn-sm btn-outline-secondary") {
+            dom.className = "btn btn-sm btn-outline-secondary active"
+            let hKeys = [`vis_outter_border`, `vis_no_border`];
+            let domIdx = hKeys.indexOf(dom.id);
+            if (domIdx >= 0) {
+                for (let idx = 0; idx < hKeys.length; idx++) {
+                    if (idx !== domIdx) {
+                        $(`#` + hKeys[idx])[0].className = "btn btn-sm btn-outline-secondary";
+                    }
+                }
+            }
+            me.setupCellBorder();
+        }
+    },
+    changeCellType: function (newType) {
+        let me = visualJumbo, sheet = me.tplWorkBook.getActiveSheet();
+        let selectedRanges = sheet.getSelections();
+        if (selectedRanges.length > 0) {
+            let cell = sheet.getCell(selectedRanges[0].row, selectedRanges[0].col);
+            switch (newType) {
+                case `field`:
+                    let rptTpl = (zTreeOprObj.currentNode)?zTreeOprObj.currentNode.rptTpl:null;
+                    let cellType = new GC.Spread.Sheets.CellTypes.ComboBox();
+                    // let selectableFields = me.getSelectedFields(rptTpl);
+                    let selectableFields = visualCommonOprObj.getAllSelectedFields(rptTpl);
+                    cellType.items(selectableFields);
+                    cell.cellType(cellType);
+                    break;
+                case `text`:
+                default:
+                    cell.cellType(new GC.Spread.Sheets.CellTypes.Text());
+                    cell.value(``);
+                    break;
+            }
+        }
+    },
+    applyBack: function () {
+        let me = visualJumbo, sheet = me.tplWorkBook.getActiveSheet();
+        let rptTpl = (zTreeOprObj.currentNode)?zTreeOprObj.currentNode.rptTpl:null;
+        let xPos = [0], yPos = [0];
+        for (let iRow = 0; iRow < sheet.getRowCount(); iRow++) {
+            xPos.push(sheet.getRowHeight(iRow) + xPos[xPos.length - 1]);
+            for (let iCol = 0; iCol < sheet.getColumnCount(); iCol++) {
+                yPos.push(sheet.getColumnWidth(iCol) + yPos[yPos.length - 1]);
+            }
+        }
+
+        if (rptTpl[JV.NODE_FLOW_INFO]) {
+            //流水式
+            me.applyBack_Flow(rptTpl, sheet, xPos, yPos);
+        } else if (rptTpl[JV.NODE_BILL_INFO]) {
+            //账单式
+            me.applyBack_Bill(rptTpl, sheet, xPos, yPos);
+        } else if (rptTpl[JV.NODE_CROSS_INFO]) {
+            //交叉式
+            //目前暂缓
+            me.applyBack_Cross(rptTpl, sheet, xPos, yPos);
+        }
+    },
+    applyBack_Flow: function (rptTpl, sheet, xPos, yPos) {
+        let me = this;
+        let startRow = -1, handledBands = [];
+        //先清除所有相关text/field节点,然后再重新生成
+        me.private_clear_flow_txt_fld_nodes();
+        let textFldArr = [], colWidthArr = [], rowHeightArr = [];
+        //1. 锚定column / content(& grouping)
+        let columnBand = visualCommonOprObj.getBandEx(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_COLUMN][JV.PROP_BAND_NAME], rptTpl);
+        handledBands.push(columnBand[JV.PROP_NAME]);
+        me.private_setup_bandHeight(columnBand[JV.PROP_NAME], columnBand, sheet);
+        startRow = me.collectSheetTxtFldByArea(sheet, me.bandMappingObj[columnBand[JV.PROP_NAME]][JV.PROP_COLOR] , textFldArr, colWidthArr, rowHeightArr);
+        let columnNodes = [];
+        for (let text of textFldArr) {
+            let node = me.createTxtNode(text, sheet, startRow, colWidthArr, rowHeightArr);
+            columnNodes.push(node);
+        }
+
+        let cotentBand = visualCommonOprObj.getBandEx(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_BAND_NAME], rptTpl);
+        handledBands.push(cotentBand[JV.PROP_NAME]);
+        me.private_setup_flow_content_height(rptTpl, cotentBand[JV.PROP_NAME], sheet);
+        textFldArr = [];
+        colWidthArr = [];
+        rowHeightArr = [];
+        startRow = me.collectSheetTxtFldByArea(sheet, me.bandMappingObj[cotentBand[JV.PROP_NAME]][JV.PROP_COLOR] , textFldArr, colWidthArr, rowHeightArr);
+        let contentNodes = [];
+        for (let field of textFldArr) {
+            let node = me.private_create_field_param_node(sheet, field, startRow, colWidthArr, rowHeightArr, rptTpl);
+            contentNodes.push(node);
+        }
+
+        //2. 锚定 统计类型
+        let pageTotalBand = visualCommonOprObj.getBandEx(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_PAGE_SUM][JV.PROP_BAND_NAME], rptTpl);
+        let pageSummaryNodes = [[], []];
+        if (pageTotalBand) {
+            handledBands.push(pageTotalBand[JV.PROP_NAME]);
+            me.private_build_txt_fld_nodes(pageTotalBand, sheet, rptTpl, pageSummaryNodes);
+        }
+
+        let segTotalBand = visualCommonOprObj.getBandEx(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_SEG_SUM][JV.PROP_BAND_NAME], rptTpl);
+        let segSummaryNodes = [[], []];
+        if (segTotalBand) {
+            handledBands.push(segTotalBand[JV.PROP_NAME]);
+            me.private_build_txt_fld_nodes(segTotalBand, sheet, rptTpl, segSummaryNodes);
+        }
+        //3. 其他就归类到离散去了
+        let discreteNodesArr = [];
+        if (me.bandMappingObj && me.bandMappingObj.items && me.bandMappingObj.items.length > 0) {
+            for (let sBandMap of me.bandMappingObj.items) {
+                if (handledBands.indexOf(sBandMap[JV.PROP_BAND_NAME]) < 0 && sBandMap[JV.PROP_COLOR] !== 'White') {
+                    let sArr = {Name: "子项", BandName: sBandMap[JV.PROP_BAND_NAME], items: [[],[]], isParent: true};
+                    let sBand = visualCommonOprObj.getBandEx(sBandMap[JV.PROP_BAND_NAME], rptTpl);
+                    if (sBand) {
+                        me.private_build_txt_fld_nodes(sBand, sheet, rptTpl, sArr.items);
+                    }
+                    if (sArr.items[0].length > 0 || sArr.items[1].length > 0) {
+                        discreteNodesArr.push(sArr);
+                    }
+                }
+            }
+        }
+        //4. 最后生成节点
+        me.private_create_tpl_flow_nodes(columnNodes, contentNodes, pageSummaryNodes, segSummaryNodes, null, discreteNodesArr);
+        displayMessage("应用提交成功!", "green", 5000, "id_vis_setup_lbl");
+    },
+    private_build_txt_fld_nodes: function (band, sheet, rptTpl, destNodes) {
+        let me = this;
+        me.private_setup_bandHeight(band[JV.PROP_NAME], band, sheet);
+        let textFldArr = [], colWidthArr = [], rowHeightArr = [];
+        let startRow = me.collectSheetTxtFldByArea(sheet, me.bandMappingObj[band[JV.PROP_NAME]][JV.PROP_COLOR] , textFldArr, colWidthArr, rowHeightArr);
+        for (let txtFld of textFldArr) {
+            if (txtFld.isField) {
+                let fldNode = me.private_create_field_param_node(sheet, txtFld, startRow, colWidthArr, rowHeightArr, rptTpl);
+                destNodes[0].push(fldNode);
+            } else {
+                let txtNode = me.createTxtNode(txtFld, sheet, startRow, colWidthArr, rowHeightArr);
+                destNodes[1].push(txtNode);
+            }
+        }
+    },
+    private_create_tpl_flow_nodes: function (columnNodes, contentNodes, pageSummaryNodes, segSummaryNodes, groupSummaryNodes, discreteNodesArr) {
+        let nodes = dataInfoMapTreeOprObj.treeObj.getNodes();
+        for (let node of nodes) {
+            if (node[JV.PROP_NAME].indexOf('_列') >= 0) {
+                //列
+                dataInfoMapTreeOprObj.treeObj.addNodes(node, -1, columnNodes, true);
+            } else if (node[JV.PROP_NAME].indexOf('数据') >= 0) {
+                //数据
+                dataInfoMapTreeOprObj.treeObj.addNodes(node, -1, contentNodes, true);
+            } else if (node[JV.PROP_NAME].indexOf('_页统计') >= 0) {
+                //页统计
+                if (pageSummaryNodes[0].length > 0) {
+                    dataInfoMapTreeOprObj.treeObj.addNodes(node.items[0], -1, pageSummaryNodes[0], true);
+                }
+                if (pageSummaryNodes[1].length > 0) {
+                    dataInfoMapTreeOprObj.treeObj.addNodes(node.items[1], -1, pageSummaryNodes[1], true);
+                }
+            } else if (node[JV.PROP_NAME].indexOf('_段统计') >= 0) {
+                //章统计
+                if (segSummaryNodes[0].length > 0) {
+                    dataInfoMapTreeOprObj.treeObj.addNodes(node.items[0], -1, segSummaryNodes[0], true);
+                }
+                if (segSummaryNodes[1].length > 0) {
+                    dataInfoMapTreeOprObj.treeObj.addNodes(node.items[1], -1, segSummaryNodes[1], true);
+                }
+            } else if (node[JV.PROP_NAME].indexOf('_分组') >= 0) {
+                //分组统计
+                // for (let subNode of node.items) {
+                //     dataInfoMapTreeOprObj.treeObj.removeChildNodes(subNode);
+                // }
+            } else if (node[JV.PROP_NAME].indexOf('离散') >= 0) {
+                //离散信息
+                if (discreteNodesArr) {
+                    for (let dNode of discreteNodesArr) {
+                        let discreteNode = {"Name": "子项", "BandName": dNode[JV.PROP_BAND_NAME], "items": [{"Name": "离散字段集", "items": [], "isParent": true},{"Name": "离散文本集", "items": [], "isParent": true}], "isParent": true};
+                        if (dNode.items[0].length > 0) {
+                            // dataInfoMapTreeOprObj.treeObj.addNodes(node.items[0], -1, segSummaryNodes[0], true);
+                            discreteNode.items[0].items = dNode.items[0];
+                        }
+                        if (dNode.items[1].length > 0) {
+                            // dataInfoMapTreeOprObj.treeObj.addNodes(node.items[1], -1, segSummaryNodes[1], true);
+                            discreteNode.items[1].items = dNode.items[1];
+                        }
+                        dataInfoMapTreeOprObj.treeObj.addNodes(node, -1, discreteNode, true);
+                    }
+                }
+            }
+        }
+
+    },
+    private_create_field_param_node: function (sheet, field, startRow, colWidthArr, rowHeightArr, rptTpl) {
+        let me = this;
+        let isAutoHeight = false;
+        if (field.text && field.text.indexOf(`{`) === 0) {
+            isAutoHeight = true;
+            field.text = field.text.replace('{', '').replace('}','');
+        }
+        let rst = {"Name": field.text, "Title": '', "FieldID": -1, "font": "Content", "control": "Column", "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;
+        let native_chk_field_param = function (fpArr) {
+            for (let rptField of fpArr) {
+                if (rptField[JV.PROP_NAME] === field.text) {
+                    rst.FieldID = rptField[JV.PROP_ID];
+                    rst["Title"] = "ID: " + rptField[JV.PROP_ID];
+                    hasChkField = true;
+                    break;
+                }
+            }
+        };
+        if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS] !== undefined && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS].length > 0) {
+            native_chk_field_param(rptTpl[JV.NODE_FIELD_MAP][JV.NODE_DETAIL_FIELDS]);
+        }
+        if (rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS] !== undefined && rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS].length > 0) {
+            native_chk_field_param(rptTpl[JV.NODE_FIELD_MAP][JV.NODE_MASTER_FIELDS]);
+        }
+        if (!hasChkField && rptTpl[JV.NODE_NO_MAPPING_FIELDS] !== undefined && rptTpl[JV.NODE_NO_MAPPING_FIELDS].length > 0) {
+            native_chk_field_param(rptTpl[JV.NODE_NO_MAPPING_FIELDS]);
+        }
+        if (!hasChkField && rptTpl[JV.NODE_DISCRETE_PARAMS] !== undefined && rptTpl[JV.NODE_DISCRETE_PARAMS].length > 0) {
+            native_chk_field_param(rptTpl[JV.NODE_DISCRETE_PARAMS]);
+            if (hasChkField) {
+                rst.ParamID = rst.FieldID;
+                delete rst.FieldID;
+            }
+        }
+
+        let cell = sheet.getCell(field.row, field.col);
+        //2. 字体
+        rst[JV.PROP_FONT] = me.private_getFontByCellProperties(cell);
+        rst[JV.PROP_STYLE] = me.private_getBorderByCellProperties(cell);
+        rst[JV.PROP_CONTROL] = me.private_getCtrlByCellProperties(cell);
+        //3. 自动行高
+        rst[JV.PROP_IS_AUTO_HEIGHT] = isAutoHeight;
+
+        //4. 左右位置%
+        me.setupHeightWidth(rst, field, startRow, colWidthArr, rowHeightArr);
+
+        return rst;
+    },
+    private_clear_flow_txt_fld_nodes: function () {
+        let nodes = dataInfoMapTreeOprObj.treeObj.getNodes();
+        for (let node of nodes) {
+            if (node[JV.PROP_NAME].indexOf('_列') >= 0 || node[JV.PROP_NAME].indexOf('数据') >= 0) {
+                //1. 列 / 数据
+                dataInfoMapTreeOprObj.treeObj.removeChildNodes(node);
+            } else if (node[JV.PROP_NAME].indexOf('_页统计') >= 0 || node[JV.PROP_NAME].indexOf('_段统计') >= 0) {
+                //3. 页统计 / 章统计
+                for (let subNode of node.items) {
+                    dataInfoMapTreeOprObj.treeObj.removeChildNodes(subNode);
+                }
+            } else if (node[JV.PROP_NAME].indexOf('_分组') >= 0) {
+                //5. 分组统计
+                for (let subNode of node.items) {
+                    dataInfoMapTreeOprObj.treeObj.removeChildNodes(subNode);
+                }
+            } else if (node[JV.PROP_NAME].indexOf('离散') >= 0) {
+                //6. 离散信息
+                dataInfoMapTreeOprObj.treeObj.removeChildNodes(node);
+            }
+        }
+    },
+    applyBack_Bill: function (rptTpl, sheet, xPos, yPos) {
+        let me = this;
+        let pageWith = xPos[xPos.length - 1];
+        //先清除所有相关text/field节点,然后再重新生成
+        me.private_clear_bill_txt_fld_nodes();
+        //1. 锚定content
+        let cotentBand = visualCommonOprObj.getBandEx(rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_BAND_NAME], rptTpl);
+        //2. 其他就归类到离散去了
+    },
+    private_clear_bill_txt_fld_nodes: function () {
+        let nodes = dataInfoMapTreeOprObj.treeObj.getNodes();
+        for (let node of nodes) {
+            dataInfoMapTreeOprObj.treeObj.removeChildNodes(node);
+        }
+    },
+    applyBack_Cross: function (rptTpl, sheet, xPos, yPos) {
+        let me = this;
+        let pageWith = xPos[xPos.length - 1];
+        //先清除所有相关text/field节点,然后再重新生成
+        me.private_clear_cross_txt_fld_nodes();
+        //1. 锚定...
+    },
+    private_clear_cross_txt_fld_nodes: function () {
+        let nodes = dataInfoMapTreeOprObj.treeObj.getNodes();
+        for (let node of nodes) {
+            //
+        }
+    },
+    private_setup_flow_content_height: function (rptTpl, bandName, sheet) {
+        let me = visualJumbo;
+        if (me.bandMappingObj[bandName]) {
+            let bandColor = me.bandMappingObj[bandName][JV.PROP_COLOR];
+            for (let iRow = 0; iRow < sheet.getRowCount(); iRow++) {
+                if (sheet.getCell(iRow, 0).backColor() === bandColor) {
+                    rptTpl[JV.NODE_FLOW_INFO][JV.NODE_FLOW_CONTENT][JV.PROP_CMN_HEIGHT] = (sheet.getRowHeight(iRow) / unitFactor).toFixed(2);
+                }
+            }
+        }
+    },
+    private_setup_bandHeight: function (bandName, band, sheet) {
+        let me = visualJumbo;
+        if (band && me.bandMappingObj[bandName]) {
+            let bandColor = me.bandMappingObj[bandName][JV.PROP_COLOR];
+            let isFirst = true, firstRowIdx = -1, lastRowIdx = -1;
+            for (let iRow = 0; iRow < sheet.getRowCount(); iRow++) {
+                if (sheet.getCell(iRow, 0).backColor() === bandColor) {
+                    lastRowIdx = iRow;
+                    if (isFirst) {
+                        firstRowIdx = iRow;
+                        isFirst = false;
+                    }
+                }
+            }
+            if (firstRowIdx >= 0) {
+                let bH = 0;
+                for (let idx = firstRowIdx; idx <= lastRowIdx; idx++) {
+                    bH += sheet.getRowHeight(idx);
+                }
+                band[JV.BAND_PROP_HEIGHT] = (bH / unitFactor).toFixed(2);
+            }
+        }
+    },
+    collectSheetTxtFldByArea: function (sheet, backColor, textArr, colWidthArr, rowHeightArr) {
+        let me = this, allSpans = sheet.getSpans();
+        let startRow = -1, endRow = -1;
+        let isFirst = true;
+        for (let idx = 0; idx < sheet.getRowCount(); idx++) {
+            if (sheet.getCell(idx, 0).backColor() === backColor) {
+                if (isFirst) {
+                    startRow = idx;
+                    isFirst = false;
+                }
+                endRow = idx;
+            }
+        }
+        let spans = [];
+        for (let span of allSpans) {
+            if (span.row >= startRow && span.row <= endRow) {
+                spans.push(span);
+            }
+        }
+        for (let span of spans) {
+            me.private_build_pre_text(sheet, textArr, span.row, span.col, span.rowCount, span.colCount);
+        }
+        for (let iRow = startRow; iRow <= endRow; iRow++) {
+            rowHeightArr.push(sheet.getRowHeight(iRow));
+            if (iRow > startRow) {
+                rowHeightArr[iRow - startRow] = rowHeightArr[iRow - startRow] + rowHeightArr[iRow - startRow - 1];
+            }
+            for (let jCol = 0; jCol < sheet.getColumnCount(); jCol++) {
+                if (iRow === startRow) {
+                    colWidthArr.push(sheet.getColumnWidth(jCol));
+                    if (jCol > 0) {
+                        colWidthArr[jCol] = colWidthArr[jCol] + colWidthArr[jCol - 1];
+                    }
+                }
+                if (!visualCommonOprObj.checkInSpan(spans, iRow, jCol)) {
+                    me.private_build_pre_text(sheet, textArr, iRow, jCol, 1, 1);
+                }
+            }
+        }
+        return startRow;
+    },
+    private_build_pre_text: function (sheet, textArr, row, col, rowCount, colCount) {
+        let cell = sheet.getCell(row, col);
+        let textValue = sheet.getValue(row, col);
+        let isField = false, isBlank = false;
+        if (textValue && cell.cellType() && cell.cellType().typeName === '7') {
+            isField = true;
+        } else {
+            isBlank = stringUtil.isEmptyString(textValue);
+        }
+        if (!isBlank) {
+            textArr.push({"row": row, "col": col, "rowCount": rowCount, "colCount": colCount, "text": textValue, "isField": isField});
+        }
+    },
+    createTxtNode: function (text, sheet, startRow, colWidthArr, rowHeightArr) {
+        let me = this, rst = dataInfoMapTreeOprObj.getDummyTextNode(null);
+        me.setupHeightWidth(rst, text, startRow, colWidthArr, rowHeightArr);
+        if (stringUtil.isEmptyString(text[`text`])) {
+            rst[JV.PROP_NAME] = '';
+        } else {
+            rst[JV.PROP_NAME] = stringUtil.replaceAll(stringUtil.replaceAll(text[`text`].toString(), '\n', '|'), '\r', '');
+        }
+        rst[JV.PROP_LABEL] = rst[JV.PROP_NAME];
+        //then setup font/border/control
+        let cell = sheet.getCell(text.row, text.col);
+        rst[JV.PROP_FONT] = me.private_getFontByCellProperties(cell);
+        rst[JV.PROP_STYLE] = me.private_getBorderByCellProperties(cell);
+        rst[JV.PROP_CONTROL] = me.private_getCtrlByCellProperties(cell);
+        return rst;
+    },
+    setupHeightWidth: function (dest, text, startRow, colWidthArr, rowHeightArr) {
+        let width = colWidthArr[colWidthArr.length - 1], height = rowHeightArr[rowHeightArr.length - 1];
+        dest[JV.PROP_AREA][JV.PROP_RIGHT] = (colWidthArr[text.col + text.colCount - 1] / width * 100).toFixed(2);
+        if (text.col > 0) {
+            dest[JV.PROP_AREA][JV.PROP_LEFT] = (colWidthArr[text.col - 1] / width * 100).toFixed(2);
+        } else {
+            dest[JV.PROP_AREA][JV.PROP_LEFT] = 0;
+        }
+        dest[JV.PROP_AREA][JV.PROP_BOTTOM] = (rowHeightArr[text.row - startRow + text.rowCount - 1] / height * 100).toFixed(2);
+        if (text.row > startRow) {
+            dest[JV.PROP_AREA][JV.PROP_TOP] = (rowHeightArr[text.row - startRow - 1] / height * 100).toFixed(2);
+        } else {
+            dest[JV.PROP_AREA][JV.PROP_TOP] = 0;
+        }
+    },
+    createDiscreteFieldNode: function (field, colWidthArr, rowHeightArr) {
+        //
+    },
+    private_getFontByCellProperties: function (cell) {
+        let me = this, rst = 'Content';
+        if (me.bandMappingObj.fontAttr[cell.row + "_" + cell.col + "_font"]) {
+            rst = me.bandMappingObj.fontAttr[cell.row + "_" + cell.col + "_font"];
+        }
+        return rst;
+    },
+    private_getBorderByCellProperties: function (cell) {
+        let rst = 'Default_None';
+        let border = cell.borderLeft();
+        if (border && border.style === GC.Spread.Sheets.LineStyle.thin) {
+            rst = 'Default_Normal'
+        }
+        return rst;
+    },
+    private_getCtrlByCellProperties: function (cell) {
+        let rst = 'Default';
+        let border = cell.borderLeft();
+        if (cell.vAlign() === GC.Spread.Sheets.VerticalAlign.center) {
+            if (border && border.style === GC.Spread.Sheets.LineStyle.thin) {
+                switch (cell.hAlign()) {
+                    case GC.Spread.Sheets.HorizontalAlign.center:
+                        rst = `Column`;
+                        break;
+                    case GC.Spread.Sheets.HorizontalAlign.right:
+                        rst = `Column_Right`;
+                        break;
+                    case GC.Spread.Sheets.HorizontalAlign.left:
+                    default:
+                        rst = `Column_Left`;
+                        break;
+                }
+            } else {
+                switch (cell.hAlign()) {
+                    case GC.Spread.Sheets.HorizontalAlign.center:
+                        rst = `Title`;
+                        break;
+                    case GC.Spread.Sheets.HorizontalAlign.right:
+                        rst = `Header_Right`;
+                        break;
+                    case GC.Spread.Sheets.HorizontalAlign.left:
+                    default:
+                        rst = `Header`;
+                        break;
+                }
+            }
+        } else {
+            switch (cell.hAlign()) {
+                case GC.Spread.Sheets.HorizontalAlign.center:
+                    rst = `Content_Center`;
+                    break;
+                case GC.Spread.Sheets.HorizontalAlign.right:
+                    rst = `Content_Right`;
+                    break;
+                case GC.Spread.Sheets.HorizontalAlign.left:
+                default:
+                    rst = `Content_Left`;
+                    break;
+            }
+        }
+        return rst;
+    }
 };