/**
 * Created by Mai on 2017/4/1.
 */

var TREE_SHEET_HELPER = {
    getObjPos: function (obj) {
        let target = obj;
        let pos = {x: obj.offsetLeft, y: obj.offsetTop};

        target = obj.offsetParent;
        while (target) {
            pos.x += target.offsetLeft;
            pos.y += target.offsetTop;
            target = target.offsetParent;
        }
        return pos;
    },
    /**
     * 初始化setting,需要提示单元格text时,必须先初始化setting
     * @param obj
     * @param setting
     */
    /*initSetting: function (obj, setting) {
        setting.pos = this.getObjPos(obj);
    },*/
    initSetting: function (obj, setting) {
        setting.pos = this.getObjPos(obj);
    },
    createNewSpread: function (obj) {
        var spread = new GC.Spread.Sheets.Workbook(obj, {sheetCount: 1});
        spread.options.tabStripVisible = false;
        spread.options.scrollbarMaxAlign = true;
        spread.options.cutCopyIndicatorVisible = false;
        spread.options.allowCopyPasteExcelStyle = false;
        spread.options.allowUserDragDrop = false;
        spread.getActiveSheet().setRowCount(3);
        return spread;
    },
    getSheetCellStyle: function (setting) {
        var style = new GC.Spread.Sheets.Style();
        //style.locked = setting.readOnly ? true : false;
        style.name = setting.id;
        //style.font = setting.data.font;
        style.hAlign = setting.data.hAlign;
        style.vAlign = setting.data.vAlign;
        style.wordWrap = setting.data.wordWrap;
        if (setting.data.formatter) {
            style.formatter = setting.data.formatter;
        }
        return style;
    },
    loadSheetHeader: function (setting, sheet) {
        this.massOperationSheet(sheet, function () {
            if(setting.rowHeaderWidth !== undefined && setting.rowHeaderWidth !== null){
                sheet.setColumnWidth(0, setting.rowHeaderWidth, GC.Spread.Sheets.SheetArea.rowHeader);
            }
            if (setting.frozenCols) {
                sheet.frozenColumnCount(setting.frozenCols);
            }
            sheet.setColumnCount(setting.cols.length);
            sheet.setRowCount(setting.headRows, GC.Spread.Sheets.SheetArea.colHeader);
            setting.headRowHeight.forEach(function (rowHeight, index) {
                sheet.setRowHeight(index, rowHeight, GC.Spread.Sheets.SheetArea.colHeader);
            });
            setting.cols.forEach(function (col, index) {
                var i, iRow = 0, cell;
                for (i = 0; i < col.head.spanCols.length; i++) {
                    if (col.head.spanCols[i] !== 0) {
                        cell = sheet.getCell(iRow, index, GC.Spread.Sheets.SheetArea.colHeader);
                        //cell.value(col.head.titleNames[i]).font(col.head.font).hAlign(col.head.hAlign[i]).vAlign(col.head.vAlign[i]).wordWrap(true);
                        cell.value(col.head.titleNames[i]).hAlign(col.head.hAlign[i]).vAlign(col.head.vAlign[i]).wordWrap(true);
                    }
                    if (col.head.spanCols[i] > 1 || col.head.spanRows[i] > 1) {
                        sheet.addSpan(iRow, index, col.head.spanRows[i], col.head.spanCols[i], GC.Spread.Sheets.SheetArea.colHeader);
                    }
                    iRow += col.head.spanRows[i];
                };
                sheet.setColumnWidth(index, col.width);
                sheet.setColumnVisible(index, col.visible && true);
            });
        });      
    },
    protectdSheet: function (sheet) {
        var option = {
            allowSelectLockedCells: true,
            allowSelectUnlockedCells: true,
            allowResizeRows: true,
            allowResizeColumns: true
        };

        sheet.options.protectionOptions = option;
        sheet.options.isProtected = true;
        sheet.options.allowCellOverflow = false;
    },
    massOperationSheet: function (sheet, Operation) {
        sheet.suspendPaint();
        sheet.suspendEvent();
        Operation();
        sheet.resumeEvent();
        sheet.resumePaint();
    },
    refreshNodesVisible: function (nodes, sheet, recursive) {
        nodes.forEach(function (node) {
            var iRow;
            iRow = node.serialNo();
            sheet.setRowVisible(iRow, node.visible, GC.Spread.Sheets.SheetArea.viewport);
            if (recursive) {
                TREE_SHEET_HELPER.refreshNodesVisible(node.children, sheet, recursive);
            }
        })
    },
    refreshTreeNodeData: function (setting, sheet, nodes, recursive,autoFit=true) {
        nodes.forEach(function (node) {
            let iRow = node.serialNo();
            if(setting.emptyRowHeader){
                sheet.setValue(iRow, 0, '', GC.Spread.Sheets.SheetArea.rowHeader);
            }
            if(typeof projectObj !== 'undefined'){
                let nodeStyle = projectObj.getNodeColorStyle(sheet, node);
                if(node.data.bgColour){
                    nodeStyle.backColor = node.data.bgColour;
                }
                if(nodeStyle){
                    sheet.setStyle(iRow, -1, nodeStyle);
                }
            }
            setting.cols.forEach(function (colSetting, iCol) {

   /* if(typeof projectObj !== 'undefined'){ 7/28  取消黑体显示
                    let boldFontStyle = projectObj.getBoldFontStyle(node, colSetting);
                    sheet.setStyle(iRow, iCol, boldFontStyle);
                }
                }*/

                // var getFieldText = function () {
                //     var fields = colSetting.data.field.split('.');
                //     var validField = fields.reduce(function (field1, field2) {
                //         if (eval('node.data.' + field1)) {
                //             return field1 + '.' + field2
                //         } else {
                //             return field1;
                //         }
                //     });
                //     if (eval('node.data.' + validField)) {
                //         return eval('node.data.' + validField);
                //     } else {
                //         return '';
                //     }
                // };
                var getFieldText2 = function () {
                    var fields = colSetting.data.field.split('.'), iField, data = node.data;
                    for (iField = 0; iField < fields.length; iField++) {
                        if (data[fields[iField]] && data[fields[iField]]!='0') {
                            data = data[fields[iField]];
                        } else {
                            return '';
                        }
                    }
                    return data;
                };
                var cell = sheet.getCell(iRow, iCol, GC.Spread.Sheets.SheetArea.viewport);
                if(sheet.name()=="mainSheet"){
                    if(colSetting.data.field=="code"){
                        let tag =null;
                        if(node.sourceType == ModuleNames.ration){//定额的时候换算子目
                            tag = node.data.adjustState?node.data.adjustState:'';
                        }
                        if(tag!=null) sheet.setTag(iRow, iCol,tag);
                    } else if (colSetting) {

                    }
                    // 单元格字体颜色
                    const foreColorFunc = MainTreeCol.foreColor[colSetting.data.field];
                    if (foreColorFunc) {
                        cell.foreColor(foreColorFunc(node));
                    }
                }
                if(colSetting.visible == false) return;//隐藏列不做其它操作
                if (colSetting.data.getText && Object.prototype.toString.apply(colSetting.data.getText) === "[object Function]") {
                    cell.value(colSetting.data.getText(node));
                }else if((colSetting.data.field=="mainBills"||(['outPutMaxPrice', 'outPutLimitPrice'].includes(colSetting.data.field)))&&MainTreeCol.mainBillsEnable(node)){//主要清单有三种状态，所以直接显示就好，不走最后的逻辑
                    cell.value(node.data[colSetting.data.field]===undefined?false:node.data[colSetting.data.field]);
                } else {
                    cell.value(getFieldText2());
                }
                if (colSetting.data.cellType && Object.prototype.toString.apply(colSetting.data.cellType) !== "[object String]") {
                    cell.cellType(colSetting.data.cellType(node,setting,colSetting.data.field));
                }
                //树节点显示列
                if(iCol == setting.treeCol) cell.cellType(TREE_SHEET_HELPER.getTreeNodeCellType(setting, sheet, node.tree,node));
                if(colSetting.data.autoHeight == true){
                    colSetting.setAutoHeight(cell,node);
                }
                //主界面分部名称点击弹窗    
                if(sheet.name()=="mainSheet" && colSetting.data.field=="name") MainTreeCol.setNameCusButton(cell,node);   

                if(colSetting.editChecking&&colSetting.editChecking(node,colSetting.data.field)){
                    cell.locked(true);
                }else if (colSetting.readOnly) {
                    if(typeof projectReadOnly !== 'undefined' && projectReadOnly){
                        cell.locked(true);
                    }else {
                        if (Object.prototype.toString.apply(colSetting.readOnly) === "[object Function]") {
                            cell.locked(colSetting.readOnly(node, colSetting.data.field));
                        } else {
                            cell.locked(true);
                        }
                    }
                } else {
                    cell.locked(typeof projectReadOnly !== 'undefined' && projectReadOnly ? true : false);
                }
            });
            if(autoFit==true && setting.setAutoFitRow){
                setting.setAutoFitRow(sheet,node)//自动行高功能比较费时，400行，启用和不启用相差2秒左右
            }
            if (recursive) {
                TREE_SHEET_HELPER.refreshTreeNodeData(setting, sheet, node.children, recursive);
            }
        });
    },
    refreshChildrenVisiable:function(sheet,tree,node,row,visiable){
        let iCount = node.posterityCount(), i, child;
        for (i = 0; i < iCount; i++) {
            child = tree.items[row + i +1];
            sheet.setRowVisible(row + i + 1, visiable?visiable:child.visible, GC.Spread.Sheets.SheetArea.viewport);
        }
       sheet.invalidateLayout();
    },
    getTipCellType: function (setting) {
        let TipCellType = function () {};
        TipCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
        TipCellType.prototype.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
            };
        };
        TipCellType.prototype.processMouseEnter = function (hitinfo) {
            let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
            let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
            let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
            let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
                zoom = hitinfo.sheet.zoom();
            let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
            let cellWidth = hitinfo.sheet.getCell(-1, hitinfo.col).width();
            let dataField = setting.cols && setting.cols[hitinfo.col].data.field || setting.header[hitinfo.col].dataCode;

            if((tag==undefined||tag=='')&&hitinfo.sheet.getCell(hitinfo.row,hitinfo.col).wordWrap()==true){//显示其它列的标记为空并且设置了自动换行
                return;
            }
            if(dataField === 'itemCharacterText' || dataField === 'jobContentText' || dataField === 'adjustState'||dataField=="name"){
                if((hitinfo.sheet.getParent() === projectObj.mainSpread||hitinfo.sheet.getParent() === tender_obj.tenderSpread) && textLength <= cellWidth)
                 return;
            }

            if(hitinfo.sheet.name()=="mainSheet"){
                if(dataField=="quantity"){//显示工程量明细
                    text = tag;
                }/*if(dataField=="name"){//项目特征及内容隐藏时，显示特征及内容
                 if(projectObj.ifItemCharHiden(setting)&&tag!=''){
                 text = tag;
                 }else if(textLength <= cellWidth){
                 return;
                 }
                 }*/
                else if(tag !== undefined && tag) {
                    text = tag;
                }
                //这里要改成延时显示
                TREE_SHEET_HELPER.delayShowTips(hitinfo,setting,text);
            }else {//非造价书页面还是实时显示
                TREE_SHEET_HELPER.showTipsDiv(text,setting,hitinfo);
            }


        };
        TipCellType.prototype.processMouseLeave = function (hitinfo) {
            TREE_SHEET_HELPER.hideTipsDiv();
        }
        return new TipCellType();
    },
    showTreeData: function (setting, sheet, tree) {
        TREE_SHEET_HELPER.protectdSheet(sheet);
        TREE_SHEET_HELPER.massOperationSheet(sheet, function () {
            sheet.rowOutlines.direction(GC.Spread.Sheets.Outlines.OutlineDirection.backward);
            sheet.showRowOutline(false);
            if (setting.defaultRowHeight) {
                sheet.defaults.rowHeight = setting.defaultRowHeight;
            }
            sheet.setRowCount(tree.count() + setting.emptyRows, GC.Spread.Sheets.SheetArea.viewport);
            sheet.getRange(tree.count(), -1, setting.emptyRows, -1).locked(true);
            setting.cols.forEach(function (colSetting, iCol) {
                sheet.setStyle(-1, iCol, TREE_SHEET_HELPER.getSheetCellStyle(colSetting));
                if (colSetting.showHint) {
                    sheet.getRange(-1, iCol, -1, 1).cellType(TREE_SHEET_HELPER.getTipCellType(setting));
                }
                if(colSetting.formatter){
                    sheet.setFormatter(-1, iCol, colSetting.formatter, GC.Spread.Sheets.SheetArea.viewport);
                }
            });
            //sheet.getRange(-1, setting.treeCol, -1, 1).cellType(new TreeNodeCellType());
            TREE_SHEET_HELPER.refreshTreeNodeData(setting, sheet, tree.roots, true);
            TREE_SHEET_HELPER.refreshNodesVisible(tree.roots, sheet, true);
        });
    },
    getTreeNodeCellType:function(setting, sheet,tree,initNode){
        let indent = 20;
        let levelIndent = -5;
        let halfBoxLength = 5;
        let halfExpandLength = 3;
    
        let isRationNode = sheet.name()=="mainSheet" && initNode.sourceType == ModuleNames.ration&&initNode.data.type == rationType.ration;


        let questionImg = document.getElementById('question_pic'),
            questionImgWidth = 16,
            questionImgHeight = 16;

        let TreeNodeCellType = function () {
            this.clickDropDown = false; //如果是点击下拉框的三角形的时候，默认展开下拉框
        };
        TreeNodeCellType.prototype =isRationNode? new GC.Spread.Sheets.CellTypes.Base(): new GC.Spread.Sheets.CellTypes.Text();//new GC.Spread.Sheets.CellTypes.Text();
        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
            if (style.backColor) {
                ctx.save();
                ctx.fillStyle = style.backColor;
                ctx.fillRect(x, y, w, h);
                ctx.restore();
            } else {
                ctx.clearRect(x, y, w, h);
            }

            // ������(x1, y1)���(��, ��), (x2, y2)�յ�(��, ��), ��ɫ
            let drawLine = function (canvas, x1, y1, x2, y2, color) {
                ctx.save();
                // ����ƫ����
                ctx.translate(0.5, 0.5);
                ctx.beginPath();
                ctx.moveTo(x1, y1);
                ctx.lineTo(x2, y2);
                ctx.strokeStyle = color;
                ctx.stroke();
                ctx.restore();
            };
            let drawExpandBox = function (ctx, x, y, w, h, centerX, centerY, expanded) {
                let rect = {}, h1, h2, offset = 1;
                rect.top = centerY - halfBoxLength;
                rect.bottom = centerY + halfBoxLength;
                rect.left = centerX - halfBoxLength;
                rect.right = centerX + halfBoxLength;

                if (rect.left < x + w) {
                    rect.right = Math.min(rect.right, x + w);

                    ctx.save();
                    // ����ƫ����
                    ctx.translate(0.5, 0.5);
                    ctx.strokeStyle = 'black';
                    ctx.beginPath();
                    ctx.moveTo(rect.left, rect.top);
                    ctx.lineTo(rect.left, rect.bottom);
                    ctx.lineTo(rect.right, rect.bottom);
                    ctx.lineTo(rect.right, rect.top);
                    ctx.lineTo(rect.left, rect.top);
                    ctx.stroke();
                    ctx.fillStyle = 'white';
                    ctx.fill();
                    ctx.restore();

                    // Draw Horizontal Line
                    h1 = centerX - halfExpandLength;
                    h2 = Math.min(centerX + halfExpandLength, x + w);
                    if (h2 > h1) {
                        drawLine(ctx, h1, centerY, h2, centerY, 'black');
                    }
                    // Draw Vertical Line
                    if (!expanded && (centerX < x + w)) {
                        drawLine(ctx, centerX, centerY - halfExpandLength, centerX, centerY + halfExpandLength, 'black');
                    }
                }
            }
            let node = tree.items[options.row];
            let showTreeLine = true;
            if (!node) { return; }

            let centerX = Math.floor(x) + node.depth() * indent + node.depth() * levelIndent + indent / 2;
            let x1 = centerX + indent / 2;
            let centerY = Math.floor((y + (y + h)) / 2);
            let y1;
            const lineColor = '#ababab';
            // Draw Sibling Line
            if (showTreeLine) {
                // Draw Horizontal Line
                if (centerX < x + w) {
                    drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, lineColor);
                }
                // Draw Vertical Line
                if (centerX < x + w) {
                    y1 = node.isLast() ? centerY : y + h;
                    if (node.isFirst() && !node.parent) {
                        drawLine(ctx, centerX, centerY, centerX, y1, lineColor);
                    } else {
                        drawLine(ctx, centerX, y, centerX, y1, lineColor);
                    }
                }
            }
            // Draw Expand Box
            if (node.children.length > 0) {
                drawExpandBox(ctx, x, y, w, h, centerX, centerY, node.expanded);
            }
            // Draw Parent Line
            if (showTreeLine) {
                var parent = node.parent, parentCenterX = centerX - indent - levelIndent;
                while (parent) {
                    if (!parent.isLast()) {
                        if (parentCenterX < x + w) {
                            drawLine(ctx, parentCenterX, y, parentCenterX, y + h, lineColor);
                        }
                    }
                    parent = parent.parent;
                    parentCenterX -= (indent + levelIndent);
                }
            };

            // Draw Text
            x = x + (node.depth() + 1) * indent +  node.depth() * levelIndent;
            w = w - (node.depth() + 1) * indent - node.depth() * levelIndent;
            GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
            //画下拉框三角形
            let sheet = options.sheet;
            if (isRationNode&& options.row === sheet.getActiveRowIndex() && options.col === sheet.getActiveColumnIndex()) {
                sheetCommonObj.drowTriangle(ctx,x+w-12,y+h/2+2);
            }
            //定额库章节树问号
            if(sheet.name() === 'stdRationLib_chapter' && this.enterCell && options.row === this.enterCell.row
                && typeof rationLibObj !== 'undefined' && rationLibObj.hasExplanationRuleText(options.row)){
                let centerX = Math.floor(x) + w - 20;
                let centerY = Math.floor((y + (y + h)) / 2);
                ctx.drawImage(questionImg, centerX + 3, centerY - 7, questionImgWidth,questionImgHeight);
            }
        };
        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
            return {
                x: x,
                y: y,
                row: context.row,
                col: context.col,
                cellStyle: cellStyle,
                cellRect: cellRect,
                sheetArea: context.sheetArea
            };
        };
        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
            //点击问号符,弹出说明、工程量计算规则窗口
            if(hitinfo.sheet.name() === 'stdRationLib_chapter' && typeof rationLibObj !== 'undefined' && rationLibObj.hasExplanationRuleText(hitinfo.row)) {
                if(hitinfo.x < hitinfo.cellRect.x + hitinfo.cellRect.width && hitinfo.x > hitinfo.cellRect.x + hitinfo.cellRect.width - questionImgWidth) {
                    rationLibObj.initQuestionModal(hitinfo.row);
                }
            }
            let offset = -1;
            let node = tree.items[hitinfo.row];
            tree.selected = node;
            if(isRationNode &&hitinfo.row === hitinfo.sheet.getActiveRowIndex() && hitinfo.col === hitinfo.sheet.getActiveColumnIndex()){
                if( hitinfo.x > hitinfo.cellRect.x + hitinfo.cellRect.width - 17){
                    this.clickDropDown = true;
                    setTimeout(function () {hitinfo.sheet.startEdit();},10);
                    return;
                }
            }
            if (!node || node.children.length === 0) { return; }
            let centerX = hitinfo.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
            let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;
            //方框外1像素内都有效
            if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 &&
                hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) {
                node.setExpanded(!node.expanded);
                let sheetName = hitinfo.sheet.name();
                if(sheetName === 'stdBillsLib_bills'){
                    sessionStorage.setItem('stdBillsLibExpState', billsLibObj.stdBillsTree.getExpState(billsLibObj.stdBillsTree.items));
                }
                else if(sheetName === 'stdRationLib_chapter'){
                    sessionStorage.setItem('stdRationLibExpState', rationLibObj.tree.getExpState(rationLibObj.tree.items));
                }
                else if(sheetName === 'stdBillsGuidance_bills'){
                    sessionStorage.setItem('stdBillsGuidanceExpState', billsGuidance.bills.tree.getExpState(billsGuidance.bills.tree.items));
                }
                TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
                    let iCount = node.posterityCount(), i, child;
                    for (i = 0; i < iCount; i++) {
                        child = tree.items[hitinfo.row + i + 1];
                        hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.visible, hitinfo.sheetArea);
                        //hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.vis(), hitinfo.sheetArea);
                    }
                    hitinfo.sheet.invalidateLayout();
                });
                hitinfo.sheet.repaint();
            }

        };
        TreeNodeCellType.prototype.processMouseEnter = function(hitinfo){
            if(hitinfo.sheet.name() === 'stdBillsGuidance_bills'){
                TREE_SHEET_HELPER.delayShowTips(hitinfo,setting);
            } else if(hitinfo.sheet.name() === 'stdRationLib_chapter'){
                if(this.enterCell==null){
                    this.enterCell={
                        row:hitinfo.row,
                        col:hitinfo.col
                    };
                    hitinfo.sheet.invalidateLayout();
                    hitinfo.sheet.repaint();
                }
            }
        };
        TreeNodeCellType.prototype.processMouseMove = function(hitinfo){//造价书主界面，当鼠标移动到单元格最右往左50个像素内时才显示悬浮提示内容
            if (hitinfo.sheet.name()!=="mainSheet") return;//只有在造价书主界面才显示
            let offset = hitinfo.cellRect.width//20;从右向左显示的像素范围   2018-11-22 这里需求又改成不悬停在编码单元格右边一部分才弹出，整个单元格都弹出，所以offset先改成单元格的宽度，防止以后又改回来
            let leftX = hitinfo.cellRect.x + hitinfo.cellRect.width;//最右边的坐标
            if(leftX - hitinfo.x <= offset){//如果鼠标移动到的位置是在显示的范围内显示悬浮提示
                TREE_SHEET_HELPER.delayShowTips(hitinfo,setting);
            }else {//如果移出了范围，隐藏悬浮提示
                TREE_SHEET_HELPER.hideTipsDiv();
            }
        };
        TreeNodeCellType.prototype.processMouseLeave = function (hitinfo) {
            TREE_SHEET_HELPER.hideTipsDiv();
            if(hitinfo.sheet.name() === 'stdRationLib_chapter') {
                this.enterCell = null;
                hitinfo.sheet.invalidateLayout();
                hitinfo.sheet.repaint();
            }
        };

        if(isRationNode){
            TreeNodeCellType.prototype.createEditorElement = function (context) {
                let div = document.createElement("div");
                div.setAttribute("gcUIElement", "gcEditingInput");
                $(div).attr("id", 'rationCheckBox');
                return div;
            };

            TreeNodeCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
                $editor = $(editorContext);
                $editor.css("position", "fixed");
                $editor.css("background", 'white');
                $editor.css("width", cellRect.width);
                $editor.css("height", cellRect.height);
                //$editor.attr("gcUIElement", "gcEditingInput");//padding:0  //value="${context.sheet.getValue(context.row,context.col)}"
                $editor.html(` <div class="input-group input-group-sm">
                                <input type="text" id="esInput" class="form-control"  autocomplete="off"  style=" background-color:${cellStyle.backColor}">
                                <div class="">                           
                                    <div class="triangle-border_dropdown tb-border_dropdown" id="esBtn" style="z-index:10; left: ${cellRect.width - 15+"px"};top:${cellRect.height/2-2+"px"}"></div>
                                </div>
                            </div>
                `);
                // <div class = "input-group-append"><button class="btn btn-outline-secondary dropdown-toggle" id="esBtn"  type="button"  aria-haspopup="true" aria-expanded="false"></button></div>
                $editor.children('div').height(cellRect.height+2);
                return $editor;
            };
            TreeNodeCellType.prototype.updateEditor = function (editorContext, cellStyle, cellRect, context) {
                let me = this;
                $(editorContext).append(`<div><ul class="es-list" style="display: block;"></ul></div>`);//<li class="" data-value="" style=""> <br></li> //background-color:${cellStyle.backColor}
                $('#esInput').val(context.sheet.getValue(context.row,context.col));
                $('#esInput').select();
                projectObj.project.Ration.getNearRations(initNode.data,function(rations){
                    if(rations.length > 0){
                        let li_html = "";
                        for(let r of rations){
                            let selfstyle = ""
                            if(r.code==initNode.data.code) selfstyle="es-list-selected" //continue; //改为不排除，标记本身
                            li_html += `<li class="es_li ${selfstyle}" data-value="${r.code}" >${r.code} ${r.name} ${r.unit}</li>`;//定额编码+空格+定额名称+空格+定额单位。
                        }
                        $(".es-list").html(li_html);
                        $(".es-list").css("min-width",cellRect.width);
                    }
                    if(me.clickDropDown == false) $(".es-list").hide();

                    $(".es-list").children(".es_li").bind('click',function (e) {
                        $('#esInput').val(this.dataset.value);
                        $(".es-list").hide();
                        context.sheet.endEdit();
                    })
                    $(".es-list").children(".es_li").hover(function(){
                        $(this).css("background-color",cellStyle.backColor);
                    },function(){
                        $(this).css("background-color","");
                    });
                    $("#esBtn").bind('click',function(e){
                        $(".es-list").toggle();
                    });
                    if( $('#esInput').val()) setCursor( $("#esInput")[0], $('#esInput').val().length)
                });
            };

            TreeNodeCellType.prototype.processKeyDown = function (e, context){ //当用isReservedKey 不拦截编辑模式时的input框ctrl + c时，在非编辑模式的ctrl + c事件也需要自已处理，所以在这里再调用一下复制命令
                //console.log(tree)
                if(e.keyCode === GC.Spread.Commands.Key.c && e.ctrlKey)  context.sheet.getParent().commandManager().execute({cmd:"copy",sheetName:context.sheet.name()});
            };
            TreeNodeCellType.prototype.isReservedKey = function (e, context) {
                return e.keyCode === GC.Spread.Commands.Key.c && e.ctrlKey && !e.shiftKey && !e.altKey;//不拦截ctrl + c事件。
            };
            TreeNodeCellType.prototype.setEditorValue = function (editor, value, context) {

                 $('#esInput').val(value);
            };
            TreeNodeCellType.prototype.getEditorValue = function (editor, context) {
                return  $('#esInput').val()!==''? $('#esInput').val():null;
            };

        }
        return new TreeNodeCellType();

    },
    showTipsDiv:function (text,setting,hitinfo) {
        if (text && text !== '') {
            if(text) text = replaceAll(/[\n]/,'<br>',text);
            if(!this._fixedTipElement){
                let div = $('#fixedTip')[0];
                if (!div) {
                    div = document.createElement("div");
                    $(div).css("padding", 5)
                        .attr("id", 'fixedTip');
                    $(div).hide();
                    document.body.insertBefore(div, null);
                }
                this._fixedTipElement = div;
            }
            $(this._fixedTipElement).width('');
            $(this._fixedTipElement).html(text);
            if (!this._toolTipElement) {
                let div = $('#autoTip')[0];
                if (!div) {
                    div = document.createElement("div");
                    $(div).addClass("message-box");
                    $(div).attr("id", 'autoTip');
                    $(div).hide();
                    document.body.insertBefore(div, null);
                }
                this._toolTipElement = div;
                $(this._toolTipElement).width('');
                //实时读取位置信息
                if(hitinfo.sheet && hitinfo.sheet.getParent().qo){
                    setting.pos = SheetDataHelper.getObjPos(hitinfo.sheet.getParent().qo);
                }
                $(this._toolTipElement).html(`<span>${text}</span><div class="triangle-border tb-border_up"></div><div class="triangle-border tb-background_up"></div>`);
                //清单指引、清单库做特殊处理
                if($(hitinfo.sheet.getParent().qo).attr('id') === 'stdBillsSpread' || $(hitinfo.sheet.getParent().qo).attr('id') === 'billsGuidance_bills'){
                    $(this._toolTipElement).html(`<span>${text}</span>`);
                    let divWidth = $(this._fixedTipElement).width(),
                        divHeight = $(this._fixedTipElement).height();
                    if(divWidth > 600){
                        divWidth = 590;
                        $(this._toolTipElement).width(divWidth);
                    }
                    let top = setting.pos.y  + hitinfo.y - divHeight / 2 < 0 ? 0 : setting.pos.y  + hitinfo.y - divHeight / 2;
                    $(this._toolTipElement).css("top", top).css("left", setting.pos.x - divWidth).css;
                } else {
                    //计算显示的初始位置
               /*   显示在单元格上方，三角形指向下的版本
                    let top = setting.pos.y + hitinfo.cellRect.y -$(this._toolTipElement).height() -26;
                    let left =  setting.pos.x + hitinfo.cellRect.x;
                    $(this._toolTipElement).css("top", top).css("left", left);*/
                    //显示在下方，三角形指
                    let top = setting.pos.y  +hitinfo.cellRect.y+ hitinfo.cellRect.height+10;
                    let left =  setting.pos.x + hitinfo.cellRect.x;
                    $(this._toolTipElement).css("top", top).css("left", left).css("max-width","500px");
                }
                $(this._toolTipElement).css('z-index', 9999);
                $(this._toolTipElement).show("fast");
                TREE_SHEET_HELPER.tipDiv = 'show';//做个标记
            }
        }
    },
    hideTipsDiv:function () {
        TREE_SHEET_HELPER.tipTimeStamp = +new Date();//这个是为了造价书清单编号树节点的那个延时显示而打的时间戳，防止已经要隐藏的提示框，延时显示
        let me = TREE_SHEET_HELPER;
        TREE_SHEET_HELPER.tipDiv = 'hide';
        if (me._toolTipElement) {
            $(me._toolTipElement).hide();
            me._toolTipElement = null;
        }
        TREE_SHEET_HELPER.tipDivCheck();//延时检查：当tips正在show的时候，就调用了hide方法，会导致tips一直存在，所以设置一个超时处理
    },
    tipDivCheck(){
        setTimeout(function () {
            let tips = $('#autoTip');
            if(TREE_SHEET_HELPER.tipDiv == 'show'){
                return;
            } else if(TREE_SHEET_HELPER.tipDiv == 'hide'&&tips){
                tips.hide();
                TREE_SHEET_HELPER._toolTipElement = null;
            }
        },600)
    },
    delayShowTips:function(hitinfo,setting,tips){//延时显示
        let delayTimes = 200; //延时时间
        let now_timeStamp = +new Date();
        TREE_SHEET_HELPER.tipTimeStamp = now_timeStamp;
        setTimeout(function () {
            if(now_timeStamp - TREE_SHEET_HELPER.tipTimeStamp == 0){//鼠标停下的时候才显示
                let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
                if(tips && tips !=""){ //有tips的话优先显示tips
                    tag = tips;
                }
                if(tag&&tag!=''){
                    TREE_SHEET_HELPER.showTipsDiv(tag,setting,hitinfo);
                }
            }
        },delayTimes);
    },
    getQuestionCellType: function (mouseDownCallback = null, hasData) {
        let img = document.getElementById('question_pic'),
            imgWidth = 16,
            imgHeight = 16;
        let QuestionCellType = function () {};
        QuestionCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
        QuestionCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
            if (style.backColor) {
                ctx.save();
                ctx.fillStyle = style.backColor;
                ctx.fillRect(x, y, w, h);
                ctx.restore();
            } else {
                ctx.clearRect(x, y, w, h);
            }
            GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
            if(this.editingCell && hasData(options.row)){
                let centerX = Math.floor(x) + w - 20;
                let centerY = Math.floor((y + (y + h)) / 2);
                ctx.drawImage(img, centerX + 3, centerY - 7, imgWidth,imgHeight);
            }
        };
        QuestionCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
            return {
                x: x,
                y: y,
                row: context.row,
                col: context.col,
                cellStyle: cellStyle,
                cellRect: cellRect,
                sheetArea: context.sheetArea
            };
        };
        QuestionCellType.prototype.processMouseDown = function (hitinfo) {
            //弹出说明等窗口
            if(this.editingCell && this.editingCell.row === hitinfo.row){
                let offSet = hitinfo.cellRect.x + hitinfo.cellRect.width;
                if(hitinfo.x < offSet && hitinfo.x > offSet - imgWidth){
                    if(mouseDownCallback && hasData(hitinfo.row)) {
                        mouseDownCallback(hitinfo.row);
                    }
                    //$('#rationQuestionModal').modal('show');
                }
            }
        };
        QuestionCellType.prototype.processMouseEnter = function (hitinfo){
            if(this.editingCell==null){
                this.editingCell={
                    row:hitinfo.row,
                    col:hitinfo.col
                };
                hitinfo.sheet.invalidateLayout();
                hitinfo.sheet.repaint();
            }
        };
        QuestionCellType.prototype.processMouseLeave = function (hitinfo) {
            this.editingCell=null;
            hitinfo.sheet.invalidateLayout();
            hitinfo.sheet.repaint();
        };
        return new QuestionCellType();
    }
};