'use strict';
/**
 *
 *
 * @author Zhong
 * @date 2018/6/1
 * @version
 */
const billsGuidance = (function () {
    function _isDef(v) {
        return typeof v !== 'undefined' && v !== null;
    }
    const locked = lockUtil.getLocked();
    let moduleName = 'stdBillsGuidance';
    //上下拖动的拖动条高度
    const verticalResize = 10;
    //自执行函数全局变量定义
    const libID = getQueryString('libID');
    //总工作内容数据
    let stdBillsJobData = [];
    //总项目特征数据
    let stdBillsFeatureData = [];
    const bills = {
        dom: $('#billsSpread'),
        workBook: null,
        cache: [],
        tree: null,
        controller: null,
        treeSetting: {
            treeCol: 0,
            emptyRows: 0,
            headRows: 1,
            headRowHeight: [40],
            defaultRowHeight: 21,
            cols: [{
                width: 200,
                readOnly: true,
                showHint: true,
                head: {
                    titleNames: ["项目编码"],
                    spanCols: [1],
                    spanRows: [1],
                    vAlign: [1],
                    hAlign: [1],
                    font: ["Arial"]
                },
                data: {
                    field: "code",
                    vAlign: 1,
                    hAlign: 0,
                    font: "Arial"
                }
            }, {
                width: 200,
                readOnly: true,
                head: {
                    titleNames: ["项目名称"],
                    spanCols: [1],
                    spanRows: [1],
                    vAlign: [1],
                    hAlign: [1],
                    font: ["Arial"]
                },
                data: {
                    field: "name",
                    vAlign: 1,
                    hAlign: 0,
                    font: "Arial"
                }
            }]
        },
        headers: [
            {name: '项目编码', dataCode: 'code', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'},
            {name: '项目名称', dataCode: 'name', width: 200, vAlign: 'center', hAlign: 'left', formatter: '@'}
        ],
        events: {
            SelectionChanged: function (sender, info) {
                billsInitSel(info.newSelections[0].row);
            }
        }
    };
    //项目指引类型
    const itemType = {
        job: 0,
        ration: 1
    };
    //项目指引复制整块localStorage key
    const itemCopyBlockKey = 'guideItemCopyBlock';
    const updateType = {
        create: 'create',
        update: 'update',
        del: 'delete'
    };
    //项目指引节点状态:展开全部、收起定额
    const itemExpandState = {
        expand: 1,
        contract: 0
    };
    //项目指引当前节点展开收缩状态,默认展开全部
    let curExpandState = 1;
    const guideItem = {
        dom: $('#guideItemSpread'),
        workBook: null,
        tree: null,
        controller: null,
        treeSetting: {
            treeCol: 0,
            emptyRows: 0,
            headRows: 1,
            headRowHeight: [40],
            defaultRowHeight: 21,
            cols: [{
                width: 400,
                readOnly: locked,
                head: {
                    titleNames: ["项目指引"],
                    spanCols: [1],
                    spanRows: [1],
                    vAlign: [1],
                    hAlign: [1],
                    font: ["Arial"]
                },
                data: {
                    field: "name",
                    vAlign: 1,
                    hAlign: 0,
                    font: "Arial"
                }
            }]
        },
        headers: [
            {name: '项目指引', dataCode: 'name', width: 400, vAlign: 'center', hAlign: 'left', formatter: '@'},
        ],
        events: {
            SelectionChanged: function (sender, info) {
                guideItemInitSel(info.newSelections[0].row)
            },
            EditEnded: function (sender, args) {
                edit(args.sheet, [{row: args.row, col: args.col}]);
            },
            RangeChanged: function (sender, args) {
                edit(args.sheet, args.changedCells);
            }
        }
    };
    //定额章节树
    const section = {
        dom: $('#sectionSpread'),
        workBook: null,
        cache: [],
        tree: null,
        controller: null,
        treeSetting: {
            treeCol: 0,
            emptyRows: 0,
            headRows: 1,
            headRowHeight: [40],
            defaultRowHeight: 21,
            cols: [{
                width: 400,
                readOnly: true,
                head: {
                    titleNames: ["名称"],
                    spanCols: [1],
                    spanRows: [1],
                    vAlign: [1],
                    hAlign: [1],
                    font: ["Arial"]
                },
                data: {
                    field: "name",
                    vAlign: 1,
                    hAlign: 0,
                    font: "Arial"
                }
            }]
        },
        headers: [
            {name: '名称', dataCode: 'name', width: 400, vAlign: 'center', hAlign: 'left', formatter: '@'},
        ],
        events: {
            SelectionChanged: function (sender, info) {
                sectionInitSel(info.newSelections[0].row)
            }
        }
    };
    const ration = {
        dom: $('#rationSpread'),
        workBook: null,
        datas: [],//所有的数据,搜索定额时,从所有数据中筛选
        cache: [],//显示在表格上的数据,添加定额可以有效根据行识别定额
        headers: [
            {name: '选择', dataCode: 'select', width: 50, vAlign: 'center', hAlign: 'center'},
            {name: '编码', dataCode: 'code', width: 110, vAlign: 'center', hAlign: 'left', formatter: '@'},
            {name: '名称', dataCode: 'name', width: 250, vAlign: 'center', hAlign: 'left', formatter: '@'},
            {name: '单位', dataCode: 'unit', width: 100, vAlign: 'center', hAlign: 'left', formatter: '@'}
        ],
        events: {
            ButtonClicked: function (sender, args) {
                if(args.sheet.isEditing()){
                    args.sheet.endEdit(true);
                }
            },
            CellDoubleClick: function (sender, args) {
                if(ration.headers[args.col].dataCode === 'name'){
                    let insertDatas = getInsertRations([args.row]);
                    if(insertDatas.length > 0){
                        insert(insertDatas, false);
                    }
                }
            }
        }
    };
    const options = {
        workBook: {
            tabStripVisible:  false,
            allowContextMenu: false,
            allowCopyPasteExcelStyle : false,
            allowExtendPasteRange: false,
            allowUserDragDrop : false,
            allowUserDragFill: false,
            scrollbarMaxAlign : true
        },
        sheet: {
            protectionOptions: {allowResizeRows: true, allowResizeColumns: true},
            clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
        }
    };
    //渲染时方法,停止渲染
    //@param {Object}sheet {Function}func @return {void}
    function renderSheetFunc(sheet, func){
        sheet.suspendEvent();
        sheet.suspendPaint();
        if(func){
            func();
        }
        sheet.resumeEvent();
        sheet.resumePaint();
    }
    //设置表选项
    //@param {Object}workBook {Object}opts @return {void}
    function setOptions (workBook, opts) {
        for(let opt in opts.workBook){
            workBook.options[opt] = opts.workBook[opt];
        }
        for(let opt in opts.sheet){
            workBook.getActiveSheet().options[opt] = opts.sheet[opt];
        }
    }
    //建表头
    //@param {Object}sheet {Array}headers @return {void}
    function buildHeader(sheet, headers) {
        let fuc = function () {
            sheet.setColumnCount(headers.length);
            sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
            for(let i = 0, len = headers.length; i < len; i++){
                sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
                sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
                if(headers[i].formatter){
                    sheet.setFormatter(-1, i, headers[i].formatter);
                }
                sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
                sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
            }
        };
        renderSheetFunc(sheet, fuc);
    }
    //表监听事件
    //@param {Object}workBook @return {void}
    function bindEvent(workBook, events) {
        if(Object.keys(events).length === 0){
            return;
        }
        const Events = GC.Spread.Sheets.Events;
        let sheet = workBook.getActiveSheet();
        for(let event in events){
            workBook.bind(Events[event], events[event]);
        }
    }
    //建表
    //@param {Object}module @return {void}
    function buildSheet(module) {
        if(!module.workBook){
            module.workBook = new GC.Spread.Sheets.Workbook(module.dom[0], {sheetCount: 1});
            let sheet = module.workBook.getActiveSheet();
            if(module === bills){
                sheet.name('stdBillsGuidance_bills');
                //默认初始可控制焦点在清单表中
                module.workBook.focus();
                sheet.options.isProtected = true;
            }
            else if(module === ration){
                sheet.options.isProtected = true;
                sheet.getRange(-1, 0, -1, 1).locked(locked);
                sheet.getRange(-1, 1, -1, -1).locked(true);
            }
            else if(module === guideItem){
                sheetCommonObj.bindEscKey(module.workBook, [{sheet: sheet, editStarting: null, editEnded: module.events.EditEnded}]);
            }
            setOptions(module.workBook, options);
            buildHeader(module.workBook.getActiveSheet(), module.headers);
            bindEvent(module.workBook, module.events);
        }
        lockUtil.lockSpreads([module.workBook], locked);
    }
    //清空表数据
    //@param {Object}sheet {Array}headers {Number}rowCount @return {void}
    function cleanData(sheet, headers, rowCount){
        renderSheetFunc(sheet, function () {
            sheet.clear(-1, 0, -1, headers.length, GC.Spread.Sheets.SheetArea.viewport, GC.Spread.Sheets.StorageType.data);
            if (rowCount >= 0) {
                sheet.setRowCount(rowCount);
            }
        });
    }
    //根据清单获取项目指引
    //@param {String}guidanceLibID {Number}billsID {Function}callback @return {void}
    function getItemsByBills(guidanceLibID, billsID, callback){
        CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: guidanceLibID, billsID: billsID}, function (rstData) {
            if(callback){
                callback(rstData);
            }
        });
    }
    //清单表焦点控制
    //@param {Number}row @return {void}
    function billsInitSel(row){
        let guideSheet = guideItem.workBook.getActiveSheet();
        cleanData(guideSheet, guideItem.headers, -1);
        let node = bills.tree.items[row];
        if(!node){
            return;
        }
        bills.tree.selected = node;
        //显示备注
        $('.main-side-bottom').find('textarea').val(node.data.comment ? node.data.comment : '');
        if(!node.guidance.tree){
            getItemsByBills(libID, node.data.ID, function (rstData) {
                initTree(node.guidance, guideSheet, guideItem.treeSetting, rstData);
                setNodesExpandState(node.guidance.tree.items, curExpandState);
                renderSheetFunc(guideSheet, function () {
                    TREE_SHEET_HELPER.refreshNodesVisible(node.guidance.tree.roots, guideSheet, true);
                });
                //设置底色
                setNodesColor(guideSheet, node.guidance.tree.items);
                //项目指引初始焦点
                guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
            });
        } else{
            setNodesExpandState(node.guidance.tree.items, curExpandState);
            node.guidance.controller.showTreeData();
            //设置底色
            setNodesColor(guideSheet, node.guidance.tree.items);
            //项目指引初始焦点
            guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0);
        }
    }
    //设置项目节点展开收起状态:展开全部、收起定额
    //@param {Array}nodes(当前清单下的所有项目指引节点) {Number}expandState(展开全部1或收起定额0).
    function setNodesExpandState(nodes, expandState) {
        if(expandState === itemExpandState.contract) {
            //找出所有定额的父节点
            let rations = _.filter(nodes, function (node) {
                return node.data.type === itemType.ration;
            });
            let rationParentIDs = [];
            for(let ration of rations){
                if(ration.data.ParentID != -1){
                    rationParentIDs.push(ration.data.ParentID);
                }
            }
            rationParentIDs = Array.from(new Set(rationParentIDs));
            let rationParentNodes = _.filter(nodes, function (node) {
                return rationParentIDs.includes(node.data.ID);
            });
            //收起定额
            for(let node of rationParentNodes){
                node.setExpanded(false);
            }
        } else {
            for(let node of nodes){
                node.setExpanded(true);
            }
        }
    }
    //根据奇偶层级设置节点底色,奇数层为蓝色(树节点深度为偶数)
    //@param {Object}sheet {Array}nodes @return {void}
    function setNodesColor(sheet, nodes) {
        const color = '#DFE8F9';
        renderSheetFunc(sheet, function () {
            for(let node of nodes){
                let style = new GC.Spread.Sheets.Style();
                style.borderLeft = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
                style.borderTop = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
                style.borderRight = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
                style.borderBottom = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
                let nDepth = node.depth();
                style.backColor = nDepth % 2 == 0 && _isDef(node.data.type) && node.data.type === itemType.job ? color : 'White';
                sheet.setStyle(node.serialNo(), -1, style);
            }
        });
    }
    //选中的节点是否全是同层节点
    //@param {Object}sheet {Array}items @return {Boolean}
    function itemsSameDepth(sheet, items) {
        let sels = sheet.getSelections();
        if(sels.length === 0 || items.length === 0){
            return false;
        }
        let depths = [];
        for(let i = 0; i < sels[0].rowCount; i++){
            let row = sels[0].row + i;
            let node = items[row];
            if(node){
                 depths.push(node.depth());
            }
        }
    }
    //节点子项是否全是工作内容
    //@param {Object}node @return {Boolean}
    function allJobChildren(node){
        for(let c of node.children){
            if(c.data.type === itemType.ration){
                return false;
            }
        }
        return true;
    }
    //节点子项是否全是定额
    //@param {Object}node @return {Boolean}
    function allRationChildren(node){
        for(let c of node.children){
            if(c.data.type === itemType.job){
                return false;
            }
        }
        return true;
    }
    //刷新按钮有效性
    //@param {Object}node @return {void}
    function refreshBtn(node){
        if (locked) {
            return;
        }
        //全部设为无效
        $('.tools-btn').children().addClass('disabled');
        $('#insertRation').addClass('disabled');
        $('#insertAll').addClass('disabled');
        $('.main-bottom-content').find('textarea').attr('readonly', true);
        //插入
        if(bills.tree.selected && bills.tree.selected.guidance.tree){
            $('#insert').removeClass('disabled');
            if(node && node.data.type === itemType.ration){
                $('#insert').addClass('disabled');
            }
        }
        //删除
        if(node){
            $('#del').removeClass('disabled');
        }
        if(node && node.data.type === itemType.job){
            //升级
            if(node.parent){
                $('#upLevel').removeClass('disabled');
                if(node.nextSibling && node.children.length > 0 && !allJobChildren(node)){
                    $('#upLevel').addClass('disabled');
                }
            }
            //降级
            if(node.preSibling){
                $('#downLevel').removeClass('disabled');
                if(node.preSibling.children.length > 0 && !allJobChildren(node.preSibling)){
                    $('#downLevel').addClass('disabled');
                }
            }
        }
        //上移
        if(node && node.preSibling){
            $('#upMove').removeClass('disabled')
        }
        //下移
        if(node && node.nextSibling){
            $('#downMove').removeClass('disabled');
        }
        //收起定额、展开全部
        $('#expandContract').removeClass('disabled');
        //插入定额
        if(node && (node.children.length === 0 || allRationChildren(node))){
            $('#insertRation').removeClass('disabled');
            $('#insertAll').removeClass('disabled');
        }
        //备注,奇数节点可用
        if(node && (node.depth() + 1) % 2 === 1 && node.data.type !== itemType.ration){
            $('.main-bottom-content').find('textarea').attr('readonly', false);
        }
    }
    //项目指引表焦点控制
    //@param {Number}row @return {void}
    function guideItemInitSel(row){
        let billsNode = bills.tree.selected;
        let node = null;
        if(billsNode && billsNode.guidance.tree){
            node = billsNode.guidance.tree.items[row];
            if(node){
                billsNode.guidance.tree.selected = node;
                //显示备注
                $('.main-bottom-content').find('textarea').val(node.data.comment ? node.data.comment : '');
            }
        }
        refreshBtn(node);
    }
    //初始化当前库名
    //@param {String} @return {void}
    function initLibName(libName) {
        $('#libName')[0].outerHTML = $('#libName')[0].outerHTML.replace("XXX清单指引", libName);
    }
    //初始化各工作表
    //@param {Array}modules @return {void}
    function initWorkBooks(modules){
        for(let module of modules){
            buildSheet(module);
        }
    }
    function tipDivCheck(){
        setTimeout(function () {
            let tips = $('#autoTip');
            if(ration.tipDiv == 'show'){
                return;
            } else if(ration.tipDiv == 'hide'&&tips){
                tips.hide();
                ration._toolTipElement = null;
            }
        },600)
    }
    //获取悬浮提示单元格
    //@param {Object}sheet @return {Object}
    function getTipCellType(sheet) {
        let 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 tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
            if(tag !== undefined && tag){
                text = tag;
            }
            if(sheet && sheet.getParent().qo){
                setting.pos = SheetDataHelper.getObjPos(sheet.getParent().qo);
            }
            let delayTimes = 500; //延时时间
            let now_timeStamp = +new Date();
            this.tipTimeStamp = now_timeStamp;
            let me = this;
            setTimeout(function () {
                if(now_timeStamp - me.tipTimeStamp == 0){//鼠标停下的时候才显示
                    if (setting.pos && text && text !== '') {
                        //固定不显示的div,存储文本获取固定div宽度,toolTipElement由于显示和隐藏,获取宽度不正确
                        if(!me._fixedTipElement){
                            let div = $('#fixedTip1')[0];
                            if (!div) {
                                div = document.createElement("div");
                                $(div).css("padding", 5)
                                    .attr("id", 'fixedTip');
                                $(div).hide();
                                document.body.insertBefore(div, null);
                            }
                            me._fixedTipElement = div;
                        }
                        $(me._fixedTipElement).width('');
                        $(me._fixedTipElement).html(text);
                        if (!me._toolTipElement) {
                            let div = $('#autoTip1')[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", "0.9rem Calibri")
                                    .css("background", "white")
                                    .css("padding", 5)
                                    .attr("id", 'autoTip1');
                                $(div).hide();
                                document.body.insertBefore(div, null);
                            }
                            me._toolTipElement = div;
                            $(me._toolTipElement).width('');
                            //实时读取位置信息
                            if(hitinfo.sheet && hitinfo.sheet.getParent().qo){
                                setting.pos = SheetDataHelper.getObjPos(hitinfo.sheet.getParent().qo);
                            }
                            $(me._toolTipElement).html(text);
                            //定额库定额特殊处理
                            if($(hitinfo.sheet.getParent().qo).attr('id') === 'rationSpread'){
                                let divWidth = $(me._fixedTipElement).width(),
                                    divHeight = $(me._fixedTipElement).height();
                                if(divWidth > 600){
                                    divWidth = 590;
                                    $(me._toolTipElement).width(divWidth);
                                }
                                let top = setting.pos.y  + hitinfo.y - divHeight < 0 ? 0 :  setting.pos.y + hitinfo.cellRect.y - divHeight;
                                $(me._toolTipElement).css("top", top).css("left", setting.pos.x - divWidth);
                            }
                            else{
                                $(me._toolTipElement).css("top", setting.pos.y + hitinfo.y +15).css("left", setting.pos.x + hitinfo.x + 15);
                            }
                            //名称
                            if(hitinfo.col === 2){
                                let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
                                    zoom = hitinfo.sheet.zoom();
                                let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
                                let textLength = me.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();
                                if(textLength > cellWidth){
                                    $(me._toolTipElement).css("top", setting.pos.y + hitinfo.y +15).css("left", setting.pos.x + hitinfo.x + 15);
                                    $(me._toolTipElement).show("fast");
                                    ration.tipDiv = 'show';//做个标记
                                }
                            }
                            else {
                                $(me._toolTipElement).show("fast");
                                ration.tipDiv = 'show';//做个标记
                            }
                        }
                    }
                }
            },delayTimes);
        };
        TipCellType.prototype.processMouseLeave = function (hininfo) {
            this.tipTimeStamp = +new Date();
            ration.tipDiv = 'hide';
            if (this._toolTipElement) {
                $(this._toolTipElement).hide();
                this._toolTipElement = null;
            }
            tipDivCheck();//延时检查:当tips正在show的时候,就调用了hide方法,会导致tips一直存在,所以设置一个超时处理
        }
        return new TipCellType();
    }
    //输出表数据(定额表)
    //@param {Object}sheet {Array}headers {Array}datas @return {void}
    function showData(sheet, headers, datas){
        let fuc = function () {
            sheet.setRowCount(datas.length);
            //复选框
            let checkBoxType = new GC.Spread.Sheets.CellTypes.CheckBox();
            let tipCellType = getTipCellType(sheet);
            sheet.setCellType(-1, 0, checkBoxType);
            for(let col = 0, cLen = headers.length; col < cLen; col++){
                for(let row = 0, rLen = datas.length; row < rLen; row++){
                    sheet.setValue(row, col, datas[row][headers[col]['dataCode']]);
                    if(col === 1){
                        sheet.setTag(row, col, datas[row]['hint']);
                    }
                }
            }
            sheet.setCellType(-1, 1, tipCellType);
            sheet.setCellType(-1, 2, tipCellType);
        };
        renderSheetFunc(sheet, fuc);
    }
    //根据定额章节树ID获取定额(从数据缓存中获取,定额数据一开始一次性拉取)
    //@param {Number}sectionId {Array}rations @return {Array}
    function getRationsBySectionId(sectionId, rations) {
        if(!sectionId || !rations){
            return [];
        }
        return _.filter(rations, {sectionId});
    }
    //定额章节树焦点控制
    //@param {Number}row @return {void}
    function sectionInitSel(row) {
        let rationSheet = ration.workBook.getActiveSheet();
        let sectionNode = section.tree ? section.tree.items[row] : null;
        if(sectionNode && sectionNode.children.length === 0){
            let sectionRations = getRationsBySectionId(sectionNode.data.ID, ration.datas);
            ration.cache = sectionRations;
            showData(rationSheet, ration.headers, sectionRations);
        }
        else {
            cleanData(rationSheet, ration.headers, 0);
        }
    }
    //初始化定额条目
    //@param {Number}rationLibId @return {void}
    function initRationItems(rationLibId){
        $.bootstrapLoading.start();
        //获取定额章节树
        let sectionSheet = section.workBook.getActiveSheet();
        CommonAjax.post('/rationRepository/api/getRationTree', {rationLibId: rationLibId}, function (sectionDatas) {
            //获取所有定额数据
            let reqEntity = {rationLibId: rationLibId, showHint: true, returnFields: '-_id code ID sectionId name unit basePrice rationGljList jobContent annotation'};
            CommonAjax.post('/rationRepository/api/getRationItemsByLib', reqEntity, function (rstData) {
                section.cache = sectionDatas;
                initTree(section, section.workBook.getActiveSheet(), section.treeSetting, sectionDatas);
                //初始焦点在第一行(切换库)
                sectionSheet.setActiveCell(0, 0);
                rstData.sort(function (a, b) {
                    let rst = 0;
                    if(a.code > b.code){
                        rst = 1;
                    }
                    else if(a.code < b.code){
                        rst = -1;
                    }
                    return rst;
                });
                ration.datas = rstData;
                sectionInitSel(0);
                $.bootstrapLoading.end();
            }, function () {
                $.bootstrapLoading.end();
            });
        }, function () {
            $.bootstrapLoading.end();
        });
    }
    //初始化定额库选择
    //@param {String}compilationId @return {void}
    function initRationLibs(compilationId){
        CommonAjax.post('/rationRepository/api/getRationLibsByCompilation', {compilationId: compilationId}, function (rstData) {
            $('#rationLibSel').empty();
            for(let rationLib of rstData){
                let opt = ``;
                $('#rationLibSel').append(opt);
            }
            //初始选择
            initRationItems(parseInt($('#rationLibSel').select().val()));
            $('#rationLibSel').change(function () {
                let rationLibId = parseInt($(this).select().val());
                initRationItems(rationLibId);
            })
        });
    }
    //清单设置悬浮提示信息
    //@param {Array}billsNodes(清单节点) {Array}jobs(总的工作内容数据) {Array}items(总的项目特征数据)
    function setBillsHint(billsNodes, jobs, items) {
        let jobsMapping = {},
            itemsMapping = {};
        for(let job of jobs){
            jobsMapping[job.id] = job;
        }
        for(let item of items){
            itemsMapping[item.id] = item;
        }
        let tagInfo = [];
        for(let billsNode of billsNodes){
            let hintArr = [];
            let billsItems = billsNode.data.items;
            if(billsItems.length > 0){
                //项目特征
                hintArr.push('项目特征:');
            }
            let itemCount = 1,
                jobCount = 1;
            for(let billsItem of billsItems){
                let itemData = itemsMapping[billsItem.id];
                if(itemData){
                    //特征值
                    let eigens = [];
                    for(let eigen of itemData.itemValue){
                        eigens.push(eigen.value);
                    }
                    eigens = eigens.join(';');
                    hintArr.push(`${itemCount}.${itemData.content}${eigens === '' ? '' : ': ' + eigens}`);
                    itemCount ++;
                }
            }
            //工作内容
            let billsJobs = billsNode.data.jobs;
            if(billsJobs.length > 0){
                hintArr.push('工作内容:');
            }
            for(let billsJob of billsJobs){
                let jobData = jobsMapping[billsJob.id];
                if(jobData){
                    hintArr.push(`${jobCount}.${jobData.content}`);
                    jobCount ++;
                }
            }
            /*if(billsNode.data.ruleText && billsNode.data.ruleText !== ''){
             hintArr.push('工程量计算规则:');
             hintArr.push(billsNode.data.ruleText);
             }
             if(billsNode.data.recharge && billsNode.data.recharge !== ''){
             hintArr.push('补注:');
             hintArr.push(billsNode.data.recharge);
             }*/
            if(hintArr.length > 0){
                tagInfo.push({row: billsNode.serialNo(), value: hintArr.join('\n')});
            }
        }
        let sheet = bills.workBook.getActiveSheet();
        renderSheetFunc(sheet, function () {
            for(let tagI of tagInfo){
                sheet.setTag(tagI.row, 0, tagI.value);
            }
        });
    }
    //初始化清单的工作内容和项目特征
    //@param {Number}billsLibId {Function}callback @return {void}
    function initJobAndCharacter(billsLibId, callback){
        CommonAjax.post('/stdBillsEditor/getJobContent', {billsLibId: billsLibId}, function (datas) {
            stdBillsJobData = datas;
            CommonAjax.post('/stdBillsEditor/getItemCharacter', {billsLibId: billsLibId}, function (datas) {
                stdBillsFeatureData = datas;
                if(callback){
                    callback();
                }
            });
        });
    }
    let billsLibId = 0;
    //获取指引库信息及关联的清单
    //@param {Number}libID {Function}callback @return {Object}
    function getLibWithBills(libID, callback){
        CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function (rstData) {
            billsLibId = rstData.guidanceLib.billsLibId;
            initRationLibs(rstData.guidanceLib.compilationId);
            bills.cache = rstData.bills;
            initLibName(rstData.guidanceLib.name);
            /*initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, bills.cache);
            //每一棵项目指引树挂在清单节点上
            for(let node of bills.tree.items){
                node.guidance = {tree: null, controller: null};
            }
            //默认初始节点
            billsInitSel(0);
            if(callback){
                callback(rstData);
            }*/
            let initDataCallback = function () {
                initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, bills.cache);
                //每一棵项目指引树挂在清单节点上
                for(let node of bills.tree.items){
                    node.guidance = {tree: null, controller: null};
                }
                //默认初始节点
                billsInitSel(0);
                if(callback){
                    callback(rstData);
                }
            };
            initJobAndCharacter(rstData.guidanceLib.billsLibId, initDataCallback);
        }, function (msg) {
            window.location.href = '/billsGuidance/main';
        });
    }
    //初始化并输出树
    //@param {Object}module {Object}sheet {Object}treeSetting {Array}datas
    function initTree(module, sheet, treeSetting, datas){
        module.tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true});
        module.controller = TREE_SHEET_CONTROLLER.createNew(module.tree, sheet, treeSetting);
        module.tree.loadDatas(datas);
        module.controller.showTreeData();
        if(module === bills){
            setBillsHint(bills.tree.items, stdBillsJobData, stdBillsFeatureData);
        }
    }
    //更新清单备注
    function updateBillsComment(updateData, callback) {
        CommonAjax.post('/stdBillsEditor/updateBills', updateData, function () {
            if (callback) {
                callback();
            }
        });
    }
    //更新项目指引
    //@param {Array}updateDatas {Function}callback @return {void}
    function updateGuideItems(updateDatas, callback){
        CommonAjax.post('/billsGuidance/api/updateItems', {updateDatas: updateDatas}, function (rstData) {
            if(callback){
                callback(rstData);
            }
        });
    }
    //编辑后自动去除换行符回车符
    const deESC = /[\r\n]/g;
    //项目指引编辑
    //@param {Object}sheet {Array}cells
    function edit(sheet, cells){
        let updateDatas = [];
        //同步节点数据
        let syncDatas = [];
        for(let cell of cells){
            let text = sheet.getValue(cell.row, cell.col);
            text = text ? text.toString() : '';
            text = text.replace(deESC, '');
            sheet.setValue(cell.row, cell.col, text);
            let node = bills.tree.selected.guidance.tree.items[cell.row];
            if(node.data.name != text){
                syncDatas.push({node: node, text: text});
                updateDatas.push({updateType: updateType.update, findData: {ID: node.getID()}, updateData: {name: text}});
            }
        }
        if(updateDatas.length > 0){
            updateGuideItems(updateDatas, function () {
                for(let syncData of syncDatas){
                    syncData.node.data.name = syncData.text;
                }
            }, function () {
                //失败恢复
                renderSheetFunc(sheet, function () {
                    for(let syncData of syncDatas){
                        sheet.setValue(syncData.node.serialNo(), 0, syncData.node.data.name ? syncData.node.data.name : '');
                    }
                });
            });
        }
    }
    //项目指引插入,支持一次插入多条数据
    //@param {Array}datas {Boolean}tobeChild(插入成为子项) {Function}callback @return {void}
    function insert(datas, tobeChild, callback = null){
        $.bootstrapLoading.start();
        let sheet = guideItem.workBook.getActiveSheet();
        let controller = bills.tree.selected.guidance.controller;
        let selected = bills.tree.selected.guidance.tree.selected;
        let updateDatas = [];
        //建立数组下标索引
        let newDataIndex = {};
        for(let i = 0; i < datas.length; i++){
            let newNodeData = {
                libID: libID, ID: uuid.v1(), ParentID: selected ? selected.getParentID() : -1, NextSiblingID: selected ? selected.getNextSiblingID() : -1,
                billsID: bills.tree.selected.getID()
            };
            //定额类型插入当前工作内容焦点行,
            if(selected && ((selected.data.type === itemType.job && datas[i].type === itemType.ration) || tobeChild)){
                newNodeData.ParentID = selected.getID();
                newNodeData.NextSiblingID = -1;
            }
            Object.assign(newNodeData, datas[i]);
            newDataIndex[i] = newNodeData;
        }
        for(let i = 0; i < datas.length; i++){
            //第一个节点
            if(i === 0){
                //非插入成子节点,更新选中节点NestSiblingID
                if(selected && !((selected.data.type === itemType.job && datas[i].type === itemType.ration) || tobeChild)){
                    updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {NextSiblingID: newDataIndex[i].ID}});
                }
            }
            //非最后一个节点
            if(i !== datas.length - 1){
                newDataIndex[i].NextSiblingID = newDataIndex[i + 1].ID;
            }
            updateDatas.push({updateType: updateType.create, updateData: newDataIndex[i]});
        }
        updateGuideItems(updateDatas, function () {
            for(let updateData of updateDatas){
                if(updateData.updateType === updateType.create){
                    let newNode = controller.insertByIDS(updateData.updateData.ID, updateData.updateData.ParentID, updateData.updateData.NextSiblingID);
                    //同步data
                    Object.assign(newNode.data, updateData.updateData);
                    sheet.setValue(newNode.serialNo(), 0, newNode.data.name);
                    refreshBtn(newNode);
                }
            }
            if(callback){
                callback();
            }
            setNodesColor(sheet, bills.tree.selected.guidance.tree.items);
            guideItem.workBook.focus(true);
            $.bootstrapLoading.end();
        });
    }
    //项目指引删除操作
    //@return {void}
    function del(){
        $.bootstrapLoading.start();
        let controller = bills.tree.selected.guidance.controller;
        let selNodes = [];
        let sheet = guideItem.workBook.getSheet(0);
        let sel = sheet.getSelections()[0];
        if(sel){
            sel.row =  sel.row === -1 ? 0 : sel.row;
            for(let i = 0; i < sel.rowCount; i++){
                if(bills.tree.selected.guidance.tree.items[sel.row + i]){
                    selNodes.push(bills.tree.selected.guidance.tree.items[sel.row + i]);
                }
            }
        }
        //选中的块节点
        let blockNodes = getBlockNodes(selNodes);
        let updateDatas = [];
        function getDelDatas(nodes){
            for (let node of nodes) {
                updateDatas.push({updateType: updateType.del, findData: {ID: node.getID()}});
                if (node.children.length > 0) {
                    getDelDatas(node.children);
                }
            }
        }
        getDelDatas(blockNodes);
        //更新相关的前节点
        for (let node of blockNodes) {
            if (node.preSibling && !blockNodes.includes(node.preSibling)) {
                let next = node;
                while (next.nextSibling && blockNodes.includes(next.nextSibling)) {
                    next = next.nextSibling;
                }
                updateDatas.push({updateType: updateType.update, findData: {ID: node.preSibling.getID()}, updateData: {NextSiblingID: next.getNextSiblingID()}});
            }
        }
        updateGuideItems(updateDatas, function () {
            controller.m_delete(blockNodes);
            guideItemInitSel(sheet.getActiveRowIndex());
            refreshBtn(bills.tree.selected.guidance.tree.selected);
            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
            $.bootstrapLoading.end();
            guideItem.workBook.focus(true)
        });
    }
    //项目指引升级
    //@return {void}
    function upLevel(){
        $.bootstrapLoading.start();
        let controller = bills.tree.selected.guidance.controller;
        let selected = bills.tree.selected.guidance.tree.selected;
        let updateDatas = [];
        //更新父节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getParentID()}, updateData: {NextSiblingID: selected.getID()}});
        //更新选中节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()},
            updateData: {ParentID: selected.parent.getParentID(), NextSiblingID: selected.parent.getNextSiblingID()}});
        if(selected.nextSibling && selected.children.length > 0){
            //更新选中节点最末子节点
            let lastChild = selected.children[selected.children.length - 1];
            updateDatas.push({updateType: updateType.update, findData: {ID: lastChild.getID()}, updateData: {NextSiblingID: -1}});
        }
        //选中节点的所有后兄弟节点成为选中节点的子项
        let selectedNextIDs = [];
        let sNext = selected.nextSibling;
        while(sNext){
            selectedNextIDs.push(sNext.getID());
            sNext = sNext.nextSibling;
        }
        for(let sID of selectedNextIDs){
            updateDatas.push({updateType: updateType.update, findData: {ID: sID}, updateData: {ParentID: selected.getID()}});
        }
        updateGuideItems(updateDatas, function () {
            controller.upLevel();
            refreshBtn(bills.tree.selected.guidance.tree.selected);
            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
            $.bootstrapLoading.end();
            guideItem.workBook.focus(true)//31574
        });
    }
    //项目指引降级
    //@return {void}
    function downLevel(){
        $.bootstrapLoading.start();
        let controller = bills.tree.selected.guidance.controller;
        let selected = bills.tree.selected.guidance.tree.selected;
        let updateDatas = [];
        //更新前兄弟节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
        //更新前兄弟节点最末子节点
        if(selected.preSibling.children.length > 0){
            let lastChild = selected.preSibling.children[selected.preSibling.children.length - 1];
            updateDatas.push({updateType: updateType.update, findData: {ID: lastChild.getID()}, updateData: {NextSiblingID: selected.getID()}});
        }
        //更新选中节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {ParentID: selected.preSibling.getID(), NextSiblingID: -1}});
        updateGuideItems(updateDatas, function () {
            controller.downLevel();
            refreshBtn(bills.tree.selected.guidance.tree.selected);
            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
            $.bootstrapLoading.end();
            guideItem.workBook.focus(true)
        });
    }
    //项目指引上移
    //@return {void}
    function upMove(){
        $.bootstrapLoading.start();
        let controller = bills.tree.selected.guidance.controller;
        let selected = bills.tree.selected.guidance.tree.selected;
        let updateDatas = [];
        //更新前节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
        //更新前前节点
        if(selected.preSibling.preSibling){
            updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.preSibling.getID()}, updateData: {NextSiblingID: selected.getID()}});
        }
        //更新选中节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {NextSiblingID: selected.preSibling.getID()}});
        updateGuideItems(updateDatas, function () {
            controller.upMove();
            refreshBtn(bills.tree.selected.guidance.tree.selected);
            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
            $.bootstrapLoading.end();
            guideItem.workBook.focus(true)
        });
    }
    //项目指引下移
    //@return {void}
    function downMove(){
        $.bootstrapLoading.start();
        let controller = bills.tree.selected.guidance.controller;
        let selected = bills.tree.selected.guidance.tree.selected;
        let updateDatas = [];
        //更新下节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getNextSiblingID()}, updateData: {NextSiblingID: selected.getID()}});
        //更新前节点
        if(selected.preSibling){
            updateDatas.push({updateType: updateType.update, findData: {ID: selected.preSibling.getID()}, updateData: {NextSiblingID: selected.getNextSiblingID()}});
        }
        //更新选中节点
        updateDatas.push({updateType: updateType.update, findData: {ID: selected.getID()}, updateData: {NextSiblingID: selected.nextSibling.getNextSiblingID()}});
        updateGuideItems(updateDatas, function () {
            controller.downMove();
            refreshBtn(bills.tree.selected.guidance.tree.selected);
            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
            $.bootstrapLoading.end();
            guideItem.workBook.focus(true)
        });
    }
    //获取定额类型的项目指引名称,通过定额转换
    //@param {Object}ration @return {String}
    function getRationItemName(ration){
        let arr = [];
        arr.push(ration.code ? ration.code : '');
        arr.push(ration.name ? ration.name : '');
        arr.push(ration.basePrice ? ration.basePrice : '');
        let rst = arr.join(' ');
        rst += `/${ration.unit ? ration.unit : ''}`;
        return rst;
    }
    //获取选中的定额表行
    //@return {Array}
    function getCheckedRationRows(all){
        let rst = [];
        let sheet = ration.workBook.getActiveSheet();
        for(let i = 0; i < sheet.getRowCount(); i++){
            // 全选
            if (all) {
                rst.push(i);
                continue;
            }
            let checked = sheet.getValue(i, 0);
            if(checked){
                rst.push(i);
            }
        }
        return rst;
    }
    //清空选中定额表行
    //@param {Array}rows @return {void}
    function clearCheckedRation(rows) {
        let sheet = ration.workBook.getActiveSheet();
        renderSheetFunc(sheet, function () {
            for(let row of rows){
                sheet.setValue(row, 0, 0);
            }
        });
    }
    //获取要插入的定额数据
    //@param {Array}rows @return {Array}
    function getInsertRations(rows){
        let rst = [];
        //当前已存在定额
        let curRationIems = [];
        let selected = bills.tree.selected.guidance.tree.selected;
        if(selected){
            if(selected.data.type === itemType.job){
                curRationIems = selected.children;
            }
            else {
                curRationIems = selected.parent ? selected.parent.children : selected.tree.roots;
            }
        }
        for(let row of rows){
            let selRation = ration.cache[row];
            if(selRation){
                //添加的定额是否已存在,不重复添加
                let isExist = false;
                for(let curRation of curRationIems){
                    if(curRation.data.rationID == selRation.ID){
                        isExist = true;
                        break;
                    }
                }
                if(!isExist){
                    rst.push({type: itemType.ration, name: getRationItemName(selRation), rationID: selRation.ID});
                }
            }
        }
        return rst;
    }
    //获取块节点父项不存在于选中节点中的节点
    //@param {Array}nodes(选中的节点) @return {Array}
    function getBlockNodes(nodes) {
        let nodeMapping = {};
        for(let node of nodes){
            nodeMapping[node.data.ID] = node;
        }
        //块节点,父项不存在于选中节点中的节点
        let blockNodes = [];
        for(let node of nodes){
            if(!nodeMapping[node.data.ParentID]){
                blockNodes.push(node);
            }
        }
        return blockNodes;
    }
    //允许复制整块,如果有多个块节点,且块节点的父项不同,则不可复制
    //@param {Array}nodes(块节点) @return {Boolean}
    function canCopyBlock(nodes) {
        if(!nodes || nodes.length === 0){
            return false;
        }
        let pID = nodes[0].data.ParentID;
        for(let node of nodes){
            if(node.data.ParentID !== pID){
                return false;
            }
        }
        return true;
    }
    //允许粘贴整块 有粘贴数据,节点存在,如果粘贴到的节点为定额数据,粘贴数据为全定额数据
    //@param {Object}node(粘贴到的节点)
    function canPasteBlock(node) {
        let pasteDatas = JSON.parse(getLocalCache(itemCopyBlockKey));
        if(!pasteDatas || pasteDatas.length === 0){
            return false;
        }
        if(!node){
            return false;
        }
        //若粘贴到定额节点,则数据须全为定额
        if(node.data.type === itemType.ration){
            for(let data of pasteDatas){
                if(data.type !== itemType.ration){
                    return false;
                }
            }
        }
        //若粘贴到非定额节点,则粘贴的顶层数据须全为非定额
        else {
            let topDatas = _.filter(pasteDatas, {ParentID: -1});
            for(let topData of topDatas){
                if(topData.type === itemType.ration){
                    return false;
                }
            }
        }
        return true;
    }
    //复制整块,将块节点下所有节点数据复制一份,并且重新生成ID、ParentID、NextSiblingID,使用localStorage存储
    //@param {Array}nodes(块节点) @return {void}
    function copyBlocks(nodes) {
        nodes = _.cloneDeep(nodes);
        //将块节点的ParentID暂时设置为-1
        for(let topNode of nodes){
            topNode.data.ParentID = -1;
        }
        let copyDatas = [];
        let copyNodes = [];
        //获取块节点包含的所有节点(包括自己)
        function containNodes(nodes) {
            for(let node of nodes){
                copyNodes.push(node);
                if(node.children.length > 0){
                    containNodes(node.children);
                }
            }
        }
        containNodes(nodes);
        for(let node of copyNodes){
            copyDatas.push(node.data);
        }
        console.log(`copyDatas`);
        console.log(copyDatas);
        setLocalCache(itemCopyBlockKey, JSON.stringify(copyDatas));
    }
    //粘贴整块,整块数据粘贴到相关节点,并成为其后项
    //@param {Object}node(粘贴到的节点) @return {void}
    function pasteBlock(node) {
        let itemObj = bills.tree.selected.guidance;
        let pasteDatas = JSON.parse(getLocalCache(itemCopyBlockKey));
        //整理ID
        let IDMapping = {};
        for(let data of pasteDatas){
            data.newID = uuid.v1();
            IDMapping[data.ID] = data;
        }
        for(let data of pasteDatas){
            let nextData = IDMapping[data.NextSiblingID];
            data.NextSiblingID = nextData ? nextData.newID : -1;
            let parentData = IDMapping[data.ParentID];
            data.ParentID = parentData ? parentData.newID : -1;
        }
        for(let data of pasteDatas){
            data.ID = data.newID;
            delete data.newID;
        }
        let updateDatas = [];
        //将最顶层的块数据的ParentID设置成粘贴到节点的ParentID,并设置新的billsID
        let topDatas = _.filter(pasteDatas, {ParentID: -1});
        for(let topData of topDatas){
            topData.ParentID = node.getParentID();
        }
        //更新数据
        //更新插入的最末顶层数据NextSiblingID
        if(node.nextSibling){
            topDatas[topDatas.length - 1].NextSiblingID = node.getNextSiblingID();
        }
        //新建节点
        for(let data of pasteDatas){
            data.libID = libID;
            data.billsID = node.data.billsID;
            delete data._id;
            updateDatas.push({updateType: updateType.create, updateData: data});
        }
        console.log(`pasteDatas`);
        console.log(pasteDatas);
        //更新粘贴到的节点的NextSiblingID
        updateDatas.push({updateType: updateType.update, findData: {ID: node.data.ID}, updateData: {NextSiblingID: topDatas[0].ID}})
        $.bootstrapLoading.start();
        updateGuideItems(updateDatas, function (rstData) {
            $.bootstrapLoading.end();
            node.data.NextSiblingID = topDatas[0].ID;
            let newNodes = itemObj.tree.insertDatasTo(node.data, pasteDatas);
            cleanData(guideItem.workBook.getActiveSheet(), guideItem.headers, -1);
            itemObj.controller.showTreeData();
            setNodesColor(guideItem.workBook.getActiveSheet(), bills.tree.selected.guidance.tree.items);
        }, function () {
            $.bootstrapLoading.end();
        });
    }
    //初始化右键菜单
    //@return {void}
    function initContextMenu() {
        $.contextMenu({
            selector: '#guideItemSpread',
            build: function($triggerElement, e){
                //控制允许右键菜单在哪个位置出现
                let sheet = guideItem.workBook.getSheet(0);
                let offset = $("#guideItemSpread").offset(),
                    x = e.pageX - offset.left,
                    y = e.pageY - offset.top;
                let target = sheet.hitTest(x, y);
                if(target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){//在表格内
                    let sel = sheet.getSelections()[0];
                    if(sel && sel.rowCount === 1){
                        sheet.setActiveCell(target.row, target.col);
                    }
                    sel = sheet.getSelections()[0];
                    let selNodes = [];
                    if(sel){
                        sel.row =  sel.row === -1 ? 0 : sel.row;
                        for(let i = 0; i < sel.rowCount; i++){
                            if(bills.tree.selected.guidance.tree.items[sel.row + i]){
                                selNodes.push(bills.tree.selected.guidance.tree.items[sel.row + i]);
                            }
                        }
                    }
                    //块节点
                    let blockNodes = getBlockNodes(selNodes);
                    //右键在多选内则不重设焦点
                    if(!sel || sel.rowCount === 1 || !(target.row >= sel.row && target.row <= sel.row + sel.rowCount - 1)){
                        sheet.setActiveCell(target.row, target.col);
                    }
                    guideItemInitSel(target.row);
                    return {
                        callback: function(){},
                        items: {
                            "copy": {
                                name: "复制整块",
                                disabled: function () {
                                    return locked || !canCopyBlock(blockNodes);
                                },
                                icon: "fa-copy",
                                callback: function (key, opt) {
                                    copyBlocks(blockNodes);
                                }},
                            "paste": {
                                name: "粘贴整块",
                                disabled: function () {
                                    let pasteNode = bills.tree.selected.guidance.tree.items[target.row];
                                    return locked || !canPasteBlock(pasteNode);
                                },
                                icon: "fa-paste",
                                callback: function (key, opt) {
                                    let pasteNode = bills.tree.selected.guidance.tree.items[target.row];
                                    pasteBlock(pasteNode);
                                }},
                            "del": {
                                name: '删除',
                                disabled: function () {
                                    let node = bills.tree.selected.guidance.tree.items[target.row];
                                    return locked || !node
                                },
                                icon: "fa-arrow-left",
                                callback: function (key, opt) {
                                    $('#delAlert').modal('show');
                                }
                            },
                            "insertSibling": {
                                name: '插入行',
                                disabled: function () {
                                    let node = bills.tree.selected.guidance.tree.items[target.row];
                                    return locked || !node || node.data.type !== itemType.job;
                                },
                                icon: "fa-arrow-left",
                                callback: function (key, opt) {
                                    insert([{type: itemType.job, name: ''}], false);
                                }
                            },
                            "insertChild": {
                                name: '插入子项',
                                disabled: function () {
                                    let node = bills.tree.selected.guidance.tree.items[target.row];
                                    return locked || !node || node.data.type !== itemType.job || !allJobChildren(node);
                                },
                                icon: 'fa-arrow-left',
                                callback: function (key, opt) {
                                    insert([{type: itemType.job, name: ''}], true);
                                }
                            }
                        }
                    };
                }
                else{
                    return false;
                }
            }
        });
    }
    //初始化个按钮点击
    //@return {void}
    function initBtn(){
        $('#insert').click(function () {
            insert([{type: itemType.job, name: ''}], false);
        });
        $('#delConfirm').click(function () {
            del();
            $('#delAlert').modal('hide');
        });
        $('#del').click(function () {
            $('#delAlert').modal('show');
        });
        $('#upLevel').click(function () {
            upLevel();
        });
        $('#downLevel').click(function () {
            downLevel();
        });
        $('#upMove').click(function () {
            upMove();
        });
        $('#downMove').click(function () {
            downMove();
        });
        //收起定额、展开全部
        $('#expandContract').click(function () {
            //目前状态时展开全部节点状态,点击则收起定额
            let tree = bills.tree.selected.guidance.tree,
                itemSheet = guideItem.workBook.getActiveSheet();
            if(curExpandState === itemExpandState.expand){
                curExpandState = itemExpandState.contract;
                $(this).html(' 展开全部');
                setNodesExpandState(tree.items, itemExpandState.contract);
            } else {
                curExpandState = itemExpandState.expand;
                $(this).html(' 收起定额');
                setNodesExpandState(tree.items, itemExpandState.expand);
            }
            renderSheetFunc(itemSheet, function () {
                TREE_SHEET_HELPER.refreshNodesVisible(tree.roots, itemSheet, true);
            });
        });
        $('#insertRation').click(function () {
            let checkedRows = getCheckedRationRows();
            let insertDatas = getInsertRations(checkedRows);
            if(insertDatas.length > 0){
                insert(insertDatas, false, function () {
                    //清空选择
                    clearCheckedRation(checkedRows);
                });
            }
            else {
                clearCheckedRation(checkedRows);
            }
        });
        // 插入全部定额
        $('#insertAll').click(function () {
            let isAll = true;
            let checkedRows = getCheckedRationRows(isAll);
            let insertDatas = getInsertRations(checkedRows);
            if(insertDatas.length > 0){
                insert(insertDatas, false);
            }
        });
        //搜索定额
        $('#searchBtn').click(function () {
            let searchStr = $('#searchText').val();
            if(!searchStr || searchStr === ''){
                ration.cache = ration.datas;
            }
            else{
                let reg = new RegExp(searchStr, 'i');
                ration.cache = _.filter(ration.datas, function (data) {
                    return reg.test(data.code) || reg.test(data.name);
                });
            }
            $('.top-content').hide();
            $('#searchCount').text(`搜索结果: ${ration.cache.length}`);
            $('#rationSearchResult').show();
            autoFlashHeight();
            ration.workBook.refresh();
            let rationSheet = ration.workBook.getActiveSheet();
            renderSheetFunc(rationSheet, function () {
                clearCheckedRation(getCheckedRationRows());
                showData(rationSheet, ration.headers, ration.cache);
            })
        });
        //关闭搜索
        $('#rationSearchResult a').click(function () {
            $('.top-content').show();
            $('#rationSearchResult').hide();
            autoFlashHeight();
            renderSheetFunc(ration.workBook.getActiveSheet(), function () {
                clearCheckedRation(getCheckedRationRows());
            });
            section.workBook.refresh();
            ration.workBook.refresh();
            $('#searchText').val('');
            //恢复章节树下的定额
            sectionInitSel(section.workBook.getActiveSheet().getActiveRowIndex());
        });
        let keyupTime = 0,
            delayTime = 500;
        function delayKeyup(callback) {
            let nowTime = Date.now();
            keyupTime = nowTime;
            setTimeout(function () {
                if (nowTime - keyupTime == 0) {
                    callback();
                }
            }, delayTime);
        }
        //执行搜索
        $('#searchText').keyup(function (e) {
            delayKeyup(function () {
                $('#searchBtn').click();
            });
        });
        //编辑清单备注
        $('.main-side-bottom').find('textarea').keyup(function () {
            let me = this;
            let node = bills.tree.selected;
            let comment = $(me).val();
            delayKeyup(function () {
                if (node) {
                    let updateData = {lastOperator: userAccount, billsLibId: billsLibId, updateId: node.getID(), field: 'comment', data: comment};
                    updateBillsComment(updateData, function () {
                        node.data.comment = comment;
                    })
                }
            });
        });
        //编辑选项备注
        $('.main-bottom-content').find('textarea').keyup(function () {
            let me = this;
            let node = bills.tree.selected.guidance.tree.selected;
            let comment = $(me).val();
            delayKeyup(function () {
                if(node){
                    let updateDatas = [{updateType: updateType.update, findData: {ID: node.getID()}, updateData: {comment: comment}}];
                    updateGuideItems(updateDatas, function (rstData) {
                        node.data.comment = comment;
                    });
                }
            });
        });
        //定额高度拖动调整
        let heightEleObj = {
            module: moduleName,
            resize: $('#deResize'),
            top: $('#topContent'),
            topSpread: $('#sectionSpread'),
            bottom: $('#bottomContent'),
            bottomSpread: $('#rationSpread')
        },
            heightLimit = {
                min: 150,
                max: `$(window).height()-$('.header').height()-$('.sidebar-tools-bar').height()-150-10`,
                notTopSpread: 0,
                notBottomSpread: 0,
            };
        SlideResize.verticalSlide(heightEleObj, heightLimit, function () {
            if(section.workBook){
                section.workBook.refresh();
            }
            if(ration.workBook){
                ration.workBook.refresh();
            }
        });
        /*slideResize(rationLibResizeEles, {min: 147, max: 680}, 'height', function() {
            //autoFlashHeight();
            if(section.workBook){
                section.workBook.refresh();
            }
            if(ration.workBook){
                ration.workBook.refresh();
            }
        });*/
        //左右拖动
        //清单表与项目指引表
        let leftElesObj = {};
        leftElesObj.module = moduleName;
        leftElesObj.resize = $('#slideResizeLeft');
        leftElesObj.parent = $('#dataRow');
        leftElesObj.left = $('#leftContent');
        leftElesObj.right = $('#midContent');
        SlideResize.horizontalSlide(leftElesObj, {min: 200, max: `$('#dataRow').width() - $('#rightContent').width() - 200`}, function () {
            refreshALlWorkBook();
        });
        //人材机表与人材机组成物表
        let rightElesObj = {};
        rightElesObj.module = moduleName;
        rightElesObj.resize = $('#slideResizeRight');
        rightElesObj.parent = $('#dataRow');
        rightElesObj.left = $('#midContent');
        rightElesObj.right = $('#rightContent');
        SlideResize.horizontalSlide(rightElesObj, {min: 200, max: `$('#dataRow').width() - $('#leftContent').width() - 200`}, function () {
            refreshALlWorkBook();
        });
    }
    //刷新全部工作簿
    //@return {void}
    function refreshALlWorkBook() {
        if (bills.workBook) {
            bills.workBook.refresh();
        }
        if (guideItem.workBook) {
            guideItem.workBook.refresh();
        }
        if (section.workBook) {
            section.workBook.refresh();
        }
        if (ration.workBook) {
            ration.workBook.refresh();
        }
        $('.main-side-bottom').find('textarea').height($('.main-side-bottom').height() - 20);
        $('.main-side-bottom').find('textarea').width($('.main-side-bottom').width() - 25);
        $('.main-bottom-content').find('textarea').height($('.main-bottom-content').height() - 20);
        $('.main-bottom-content').find('textarea').width($('.main-bottom-content').width() - 25);
    }
    //读取拖动相关
    //@return {void}
    function initSlideSize() {
        //定额表上下
        let heightEleObj = {
            module: moduleName,
            top: $('#topContent'),
            topSpread: $('#sectionSpread'),
            bottom: $('#bottomContent'),
            bottomSpread: $('#rationSpread')
        };
        SlideResize.loadVerticalHeight(heightEleObj.module, heightEleObj,
            {totalHeight: `$(window).height()-$('.header').height()-$('.sidebar-tools-bar').height()-10`,
             notTopSpread: 0, notBottomSpread: 0}, function () {
                if(section.workBook){
                    section.workBook.refresh();
                }
                if(ration.workBook){
                    ration.workBook.refresh();
                }
            });
        //水平
        SlideResize.loadHorizonWidth(moduleName, [$('#slideResizeLeft'), $('#slideResizeRight')], [$('#leftContent'), $('#midContent'), $('#rightContent')], function () {
            refreshALlWorkBook();
        });
    }
    //初始化视图
    //@param {void} @return {void}
    function initViews(){
        let modules = [bills, guideItem, section, ration];
        initWorkBooks(modules);
        lockUtil.lockTools($(document.body), locked);
        getLibWithBills(libID);
        initBtn();
        initContextMenu();
        initSlideSize();
    }
    return {initViews, initSlideSize};
})();
$(document).ready(function () {
    billsGuidance.initViews();
});