|  | @@ -375,6 +375,7 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |       * @param setting
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      initSheet: function (sheet, setting) {
 | 
	
		
			
				|  |  | +        const self = this;
 | 
	
		
			
				|  |  |          this.beginMassOperation(sheet);
 | 
	
		
			
				|  |  |          this._loadCacheSetting(sheet, setting);
 | 
	
		
			
				|  |  |          setting.pos = sheet.getParent().pos;
 | 
	
	
		
			
				|  | @@ -389,6 +390,10 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |          this._initSheetHeader(sheet);
 | 
	
		
			
				|  |  |          sheet.setRowCount(sheet.zh_setting.emptyRows);
 | 
	
		
			
				|  |  |          sheet.extendCellType = {};
 | 
	
		
			
				|  |  | +        sheet.extendRowHeader = {};
 | 
	
		
			
				|  |  | +        sheet.zh_setting.rowHeader && sheet.zh_setting.rowHeader.forEach(function (col, j) {
 | 
	
		
			
				|  |  | +            self._defineRowHeader(sheet, j, col);
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  |          sheet.borderLine = new spreadNS.LineBorder('#cccccc', spreadNS.LineStyle.thin);
 | 
	
		
			
				|  |  |          sheet.getRange(0, 0, sheet.getRowCount(), sheet.getColumnCount()).locked(setting.readOnly).setBorder(sheet.borderLine, {all: true});
 | 
	
		
			
				|  |  |          if (setting.selectedBackColor) {
 | 
	
	
		
			
				|  | @@ -573,6 +578,20 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |              sheet.AcitveRefresh = true;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +    _defineRowHeader: function (sheet, col, colSetting) {
 | 
	
		
			
				|  |  | +        if (colSetting.rowHeaderType === 'tag') {
 | 
	
		
			
				|  |  | +            if (!sheet.extendRowHeader.tag) {
 | 
	
		
			
				|  |  | +                sheet.extendRowHeader.tag = this.RowHeader.getTagRowHeader(colSetting.setting);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            sheet.getRange(-1, col, -1, 1, spreadNS.SheetArea.rowHeader).cellType(sheet.extendRowHeader.tag);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (colSetting.rowHeaderType === 'circle') {
 | 
	
		
			
				|  |  | +            if (!sheet.extendRowHeader.multiTag) {
 | 
	
		
			
				|  |  | +                sheet.extendRowHeader.multiTag = this.RowHeader.getCircleTagRowHeader(colSetting.setting);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            sheet.getRange(-1, col, -1, 1, spreadNS.SheetArea.rowHeader).cellType(sheet.extendRowHeader.multiTag);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |      _defineColCellType: function (sheet, col, colSetting) {
 | 
	
		
			
				|  |  |          sheet.AcitveComboRefresh = false;
 | 
	
		
			
				|  |  |          if(colSetting.cellType === 'ellipsis') {
 | 
	
	
		
			
				|  | @@ -819,13 +838,30 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |      reLoadNodesData: function (sheet, nodes) {
 | 
	
		
			
				|  |  |          this.beginMassOperation(sheet);
 | 
	
		
			
				|  |  | -        nodes = nodes instanceof Array ? nodes : [nodes];
 | 
	
		
			
				|  |  | +        nodes = nodes instanceof Array ? nodes : [nodes];rectangle
 | 
	
		
			
				|  |  | +        const sortData = sheet.zh_dataType === 'tree' ? sheet.zh_tree.nodes : sheet.zh_data;
 | 
	
		
			
				|  |  |          for (const node of nodes) {
 | 
	
		
			
				|  |  | -            const sortData = sheet.zh_dataType === 'tree' ? sheet.zh_tree.nodes : sheet.zh_data;
 | 
	
		
			
				|  |  |              this._loadRowData(sheet, node, sortData.indexOf(node));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          this.endMassOperation(sheet);
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +    repaintNodesRowHeader: function (sheet, nodes) {
 | 
	
		
			
				|  |  | +        nodes = nodes instanceof Array ? nodes : [nodes];
 | 
	
		
			
				|  |  | +        const sortData = sheet.zh_dataType === 'tree' ? sheet.zh_tree.nodes : sheet.zh_data;
 | 
	
		
			
				|  |  | +        const rowIndex = [];
 | 
	
		
			
				|  |  | +        for (const node of nodes) {
 | 
	
		
			
				|  |  | +            rowIndex.push(sortData.indexOf(node));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        this.repaintRowsRowHeader(sheet, rowIndex);
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +    repaintRowsRowHeader: function (sheet, rows) {
 | 
	
		
			
				|  |  | +        for (const r of rows) {
 | 
	
		
			
				|  |  | +            const cellRect = sheet.getCellRect(r, 0);
 | 
	
		
			
				|  |  | +            cellRect.width = cellRect.x;
 | 
	
		
			
				|  |  | +            cellRect.x = 0;
 | 
	
		
			
				|  |  | +            sheet.repaint(cellRect);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  |       * 根据data加载sheet数据,合并了一般数据和树结构数据的加载
 | 
	
		
			
				|  |  |       * @param {GC.Spread.Sheets.Worksheet} sheet
 | 
	
	
		
			
				|  | @@ -981,6 +1017,19 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  | +    getRowObject: function (sheet, row) {
 | 
	
		
			
				|  |  | +        if (!sheet) {
 | 
	
		
			
				|  |  | +            return null;
 | 
	
		
			
				|  |  | +        } else if (sheet.zh_dataType) {
 | 
	
		
			
				|  |  | +            if (sheet.zh_dataType === this.DataType.Tree) {
 | 
	
		
			
				|  |  | +                return sheet.zh_tree.nodes[row];
 | 
	
		
			
				|  |  | +            } else if (sheet.zh_dataType === this.DataType.Data) {
 | 
	
		
			
				|  |  | +                return sheet.zh_data[row];
 | 
	
		
			
				|  |  | +            } else {
 | 
	
		
			
				|  |  | +                return null;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  |       * 刷新列显示
 | 
	
		
			
				|  |  |       * @param sheet
 | 
	
	
		
			
				|  | @@ -1206,6 +1255,7 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |                      canvas.clearRect(x, y, w, h);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                  const tree = options.sheet.zh_tree;
 | 
	
		
			
				|  |  |                  // 使用TreeCellType前,需定义sheet.tree
 | 
	
		
			
				|  |  |                  if (tree) {
 | 
	
	
		
			
				|  | @@ -1960,7 +2010,7 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |          getHtmlCellType: function () {
 | 
	
		
			
				|  |  |              const HTMLCellType = function (){};
 | 
	
		
			
				|  |  |              HTMLCellType.prototype = new spreadNS.CellTypes.Text;
 | 
	
		
			
				|  |  | -            const proto = ImageCellType.prototype;
 | 
	
		
			
				|  |  | +            const proto = HTMLCellType.prototype;
 | 
	
		
			
				|  |  |              proto.paint = function (ctx, value, x, y, w, h, style, context) {
 | 
	
		
			
				|  |  |                  let DOMURL = window.URL || window.webkitURL || window;
 | 
	
		
			
				|  |  |                  let cell = context.sheet.getCell(context.row, context.col);
 | 
	
	
		
			
				|  | @@ -2185,6 +2235,170 @@ const SpreadJsObj = {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      },
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    RowHeader: {
 | 
	
		
			
				|  |  | +        getTagRowHeader: function (setting) {
 | 
	
		
			
				|  |  | +            const indent = 16, maxHintWidth = 200, borderIndent = 10;
 | 
	
		
			
				|  |  | +            const drawTag = function (canvas, x, y, fillColor) {
 | 
	
		
			
				|  |  | +                canvas.save();
 | 
	
		
			
				|  |  | +                // 设置偏移量
 | 
	
		
			
				|  |  | +                canvas.translate(0.5, 0.5);
 | 
	
		
			
				|  |  | +                canvas.beginPath();
 | 
	
		
			
				|  |  | +                canvas.moveTo(x, y);
 | 
	
		
			
				|  |  | +                canvas.lineTo(x, y+5);
 | 
	
		
			
				|  |  | +                canvas.lineTo(x+6, y+11);
 | 
	
		
			
				|  |  | +                canvas.lineTo(x+11, y+6);
 | 
	
		
			
				|  |  | +                canvas.lineTo(x+5, y);
 | 
	
		
			
				|  |  | +                canvas.lineTo(x, y);
 | 
	
		
			
				|  |  | +                canvas.stroke();
 | 
	
		
			
				|  |  | +                canvas.fillStyle = fillColor instanceof Array ? fillColor[0] : fillColor;
 | 
	
		
			
				|  |  | +                canvas.fill();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                canvas.beginPath();
 | 
	
		
			
				|  |  | +                canvas.arc(x+2, y+2, 1, 0, Math.PI*2, true);
 | 
	
		
			
				|  |  | +                canvas.closePath();
 | 
	
		
			
				|  |  | +                canvas.fillStyle = 'white';
 | 
	
		
			
				|  |  | +                canvas.fill();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                if (fillColor instanceof Array && fillColor.length > 1) {
 | 
	
		
			
				|  |  | +                    canvas.fillStyle = '#444444';
 | 
	
		
			
				|  |  | +                    canvas.font="9px 微软雅黑";
 | 
	
		
			
				|  |  | +                    canvas.fillText(fillColor.length, x+13, y+14);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                canvas.restore();
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            let TagCellType = function (){};
 | 
	
		
			
				|  |  | +            TagCellType.prototype = new spreadNS.CellTypes.RowHeader();
 | 
	
		
			
				|  |  | +            const proto = TagCellType.prototype;
 | 
	
		
			
				|  |  | +            proto.getTagColor = setting.getColor;
 | 
	
		
			
				|  |  | +            proto.getTagHtml = setting.getTagHtml;
 | 
	
		
			
				|  |  | +            proto.basePaint = proto.paint;
 | 
	
		
			
				|  |  | +            proto.paint = function (canvas, value, x, y, w, h, style, options) {
 | 
	
		
			
				|  |  | +                spreadNS.CellTypes.RowHeader.prototype.paint.apply(this, [canvas, '', x, y, w , h, style, options]);
 | 
	
		
			
				|  |  | +                spreadNS.CellTypes.Text.prototype.paint.apply(this, [canvas, value, x, y, w - indent, h, style, options]);
 | 
	
		
			
				|  |  | +                const node = SpreadJsObj.getRowObject(options.sheet, options.row);
 | 
	
		
			
				|  |  | +                const color = this.getTagColor(options.row, node);
 | 
	
		
			
				|  |  | +                const centerX = x + w - indent + 4, centerY = y + h/2;
 | 
	
		
			
				|  |  | +                color && drawTag(canvas, centerX - 6, centerY - 6, color);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            /**
 | 
	
		
			
				|  |  | +             * 获取点击信息
 | 
	
		
			
				|  |  | +             * @param {Number} x
 | 
	
		
			
				|  |  | +             * @param {Number} y
 | 
	
		
			
				|  |  | +             * @param {Object} cellStyle
 | 
	
		
			
				|  |  | +             * @param {Object} cellRect
 | 
	
		
			
				|  |  | +             * @param {Object} context
 | 
	
		
			
				|  |  | +             * @returns {{x: *, y: *, row: *, col: *|boolean|*[]|number|{}|UE.dom.dtd.col, cellStyle: *, cellRect: *, sheet: *|StyleSheet, sheetArea: *}}
 | 
	
		
			
				|  |  | +             */
 | 
	
		
			
				|  |  | +            proto.getHitInfo = function (x, y, cellStyle, cellRect, context) {
 | 
	
		
			
				|  |  | +                return {
 | 
	
		
			
				|  |  | +                    x: x,
 | 
	
		
			
				|  |  | +                    y: y,
 | 
	
		
			
				|  |  | +                    row: context.row,
 | 
	
		
			
				|  |  | +                    col: context.col,
 | 
	
		
			
				|  |  | +                    cellStyle: cellStyle,
 | 
	
		
			
				|  |  | +                    cellRect: cellRect,
 | 
	
		
			
				|  |  | +                    sheet: context.sheet,
 | 
	
		
			
				|  |  | +                    sheetArea: context.sheetArea,
 | 
	
		
			
				|  |  | +                    ctx: context.sheet.getParent().xs,
 | 
	
		
			
				|  |  | +                };
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            /**
 | 
	
		
			
				|  |  | +             * 鼠标进入单元格事件 - 显示悬浮提示
 | 
	
		
			
				|  |  | +             * @param {Object} hitinfo - 见getHitInfo返回值
 | 
	
		
			
				|  |  | +             */
 | 
	
		
			
				|  |  | +            proto.processMouseEnter = function (hitinfo) {
 | 
	
		
			
				|  |  | +                const node = SpreadJsObj.getRowObject(hitinfo.sheet, hitinfo.row);
 | 
	
		
			
				|  |  | +                let html = this.getTagHtml(hitinfo.row, node);
 | 
	
		
			
				|  |  | +                const pos = SpreadJsObj.getObjPos(hitinfo.sheet.getParent().qo);
 | 
	
		
			
				|  |  | +                if (pos && html) {
 | 
	
		
			
				|  |  | +                    if (!this._tagTipElement) {
 | 
	
		
			
				|  |  | +                        let div = $('#autoTip')[0];
 | 
	
		
			
				|  |  | +                        if (!div) {
 | 
	
		
			
				|  |  | +                            div = document.createElement("div");
 | 
	
		
			
				|  |  | +                            $(div).css("position", "absolute")
 | 
	
		
			
				|  |  | +                                .css("border", "1px #C0C0C0 solid")
 | 
	
		
			
				|  |  | +                                .css("box-shadow", "1px 2px 5px rgba(0,0,0,0.4)")
 | 
	
		
			
				|  |  | +                                .css("font", "9pt Arial")
 | 
	
		
			
				|  |  | +                                .css("background", "white")
 | 
	
		
			
				|  |  | +                                .css("padding", 5)
 | 
	
		
			
				|  |  | +                                .css("width", maxHintWidth)
 | 
	
		
			
				|  |  | +                                .css("z-index", 999)
 | 
	
		
			
				|  |  | +                                .attr("id", 'autoTagTip')
 | 
	
		
			
				|  |  | +                                .css("top", pos.y + hitinfo.y + indent)
 | 
	
		
			
				|  |  | +                                .css("left", pos.x + hitinfo.x + indent)
 | 
	
		
			
				|  |  | +                                .html(html);
 | 
	
		
			
				|  |  | +                            document.body.insertBefore(div, null);
 | 
	
		
			
				|  |  | +                        }
 | 
	
		
			
				|  |  | +                        this._tagTipElement = div;
 | 
	
		
			
				|  |  | +                        $(div).show("fast");
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            /**
 | 
	
		
			
				|  |  | +             * 鼠标移出单元格事件 - 隐藏悬浮提示
 | 
	
		
			
				|  |  | +             * @param {Object} hitinfo - 见getHitInfo返回值
 | 
	
		
			
				|  |  | +             */
 | 
	
		
			
				|  |  | +            proto.processMouseLeave = function (hitinfo) {
 | 
	
		
			
				|  |  | +                if (this._tagTipElement) {
 | 
	
		
			
				|  |  | +                    $(this._tagTipElement).hide().remove();
 | 
	
		
			
				|  |  | +                    this._tagTipElement = null;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            return new TagCellType();
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +        getCircleTagRowHeader: function (setting) {
 | 
	
		
			
				|  |  | +            const drawCircle = function (canvas, x, y, r, fillColor) {
 | 
	
		
			
				|  |  | +                canvas.save();
 | 
	
		
			
				|  |  | +                canvas.beginPath();
 | 
	
		
			
				|  |  | +                canvas.arc(x, y, r, 0, Math.PI*2, true);
 | 
	
		
			
				|  |  | +                canvas.closePath();
 | 
	
		
			
				|  |  | +                canvas.fillStyle = fillColor;
 | 
	
		
			
				|  |  | +                canvas.fill();
 | 
	
		
			
				|  |  | +                canvas.restore();
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            const drawCircle2 = function (canvas, x, y, r, lineColor, fillColor) {
 | 
	
		
			
				|  |  | +                canvas.save();
 | 
	
		
			
				|  |  | +                canvas.beginPath();
 | 
	
		
			
				|  |  | +                canvas.arc(x, y, r, 0, Math.PI*2, true);
 | 
	
		
			
				|  |  | +                canvas.closePath();
 | 
	
		
			
				|  |  | +                canvas.fillStyle = lineColor;
 | 
	
		
			
				|  |  | +                canvas.fill();
 | 
	
		
			
				|  |  | +                canvas.beginPath();
 | 
	
		
			
				|  |  | +                canvas.arc(x, y, r-2, 0, Math.PI*2, true);
 | 
	
		
			
				|  |  | +                canvas.closePath();
 | 
	
		
			
				|  |  | +                canvas.fillStyle = fillColor;
 | 
	
		
			
				|  |  | +                canvas.fill();
 | 
	
		
			
				|  |  | +                canvas.restore();
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            let CircleTagCellType = function (){};
 | 
	
		
			
				|  |  | +            CircleTagCellType.prototype = new spreadNS.CellTypes.RowHeader();
 | 
	
		
			
				|  |  | +            const proto = CircleTagCellType.prototype;
 | 
	
		
			
				|  |  | +            proto.indent = setting.indent || 16;
 | 
	
		
			
				|  |  | +            proto.getTagColor = setting.getColor;
 | 
	
		
			
				|  |  | +            proto.basePaint = proto.paint;
 | 
	
		
			
				|  |  | +            proto.paint = function (canvas, value, x, y, w, h, style, options) {
 | 
	
		
			
				|  |  | +                spreadNS.CellTypes.RowHeader.prototype.paint.apply(this, [canvas, '', x, y, w , h, style, options]);
 | 
	
		
			
				|  |  | +                spreadNS.CellTypes.Text.prototype.paint.apply(this, [canvas, value, x, y, w - this.indent, h, style, options]);
 | 
	
		
			
				|  |  | +                const node = SpreadJsObj.getRowObject(options.sheet, options.row);
 | 
	
		
			
				|  |  | +                let sel = options.sheet.getSelections();
 | 
	
		
			
				|  |  | +                sel = sel ? sel[0] : null;
 | 
	
		
			
				|  |  | +                const actualStyle = options.sheet.getActualStyle(options.row, options.col, options.sheetArea, false);
 | 
	
		
			
				|  |  | +                if (options.row === 1) console.log(actualStyle);
 | 
	
		
			
				|  |  | +                const backColor = style.backColor || (sel && options.row >= sel.row && options.row < sel.row + sel.rowCount ? '#dddfe1' : '#e9ecef');
 | 
	
		
			
				|  |  | +                let color = this.getTagColor(options.row, node);
 | 
	
		
			
				|  |  | +                color = color instanceof Array ? color : [color];
 | 
	
		
			
				|  |  | +                for (let i = color.length - 1; i >= 0; i--) {
 | 
	
		
			
				|  |  | +                    drawCircle2(canvas, x + w - this.indent + 5 + i*5 , y + h/2, 6, backColor, color[i]);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            };
 | 
	
		
			
				|  |  | +            return new CircleTagCellType();
 | 
	
		
			
				|  |  | +        },
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      Formatter: {
 | 
	
		
			
				|  |  |          baseNumberFormatter: function () {
 | 
	
		
			
				|  |  |              const formatter = function () {};
 |