'use strict'; /** * * * @author Zhong * @date 2018/6/11 * @version */ //清单指引/精灵获取完清单数据后的回调函数 let doAfterLoadGuidance = null; //选项单选多选状态(按住alt为多选) 单选:0 多选:1 let billsGuidanceSelMode = 0; const billsGuidance = (function () { let currentLib = null; //库类型 const libType = {'guidance': 1, 'elf': 2}; //清单指引、清单精灵 const libTypeText = {1: '清单指引', 2: '清单精灵'}; const libSel = $('#stdBillsGuidanceLibSelect'); //工作内容 let stdBillsJobData = []; //项目特征 let stdBillsFeatureData = []; const bills = { dom: $('#billsGuidance_bills'), workBook: null, cache: [], tree: null, controller: null, treeSetting: { emptyRowHeader: true, rowHeaderWidth: 15, treeCol: 0, emptyRows: 0, headRows: 1, headRowHeight: [40], defaultRowHeight: 21, cols: [{ width: 140, 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: 190, readOnly: true, head: { titleNames: ["项目名称"], spanCols: [1], spanRows: [1], vAlign: [1], hAlign: [1], font: ["Arial"] }, data: { field: "name", vAlign: 1, hAlign: 0, font: "Arial" } }, { width: 45, readOnly: true, head: { titleNames: ["计量单位"], spanCols: [1], spanRows: [1], vAlign: [1], hAlign: [1], font: ["Arial"] }, data: { field: "unit", vAlign: 1, hAlign: 1, font: "Arial" } } ] }, headers: [ {name: '项目编码', dataCode: 'code', width: 140, vAlign: 'center', hAlign: 'left', formatter: '@'}, {name: '项目名称', dataCode: 'name', width: 190, vAlign: 'center', hAlign: 'left', formatter: '@'}, {name: '单位', dataCode: 'unit', width: 45, vAlign: 'center', hAlign: 'center', formatter: '@'}, ], events: { SelectionChanging: function (sender, info) { billsInitSel(info.newSelections[0].row); }, CellDoubleClick: function (sender, args) { if(!bills.tree){ return; } let node = bills.tree.items[args.row]; if(!node){ return; } if(node.children.length === 0){ //插入清单 if (/\//.test(node.data.unit)) { let canAdd = true; $.bootstrapLoading.start(); let existB = projectObj.project.Bills.sameStdCodeBillsData(node.data.code); if (existB) { let std = JSON.parse(JSON.stringify(node.data)); std.unit = existB.unit; canAdd = ProjectController.addBills(projectObj.project, projectObj.mainController, std); if(canAdd !== null || canAdd !== false){ //插入选中的定额 let addRationDatas = currentLib.type && currentLib.type === libType.elf ? getInsertElfRationData() : getInsertRationData(getCheckedRows()); insertRations(addRationDatas); } if(canAdd === false && $.bootstrapLoading.isLoading()){ $.bootstrapLoading.end(); } } else { ConfirmModal.stdBillsUnit.check(node.data, function (std) { canAdd = ProjectController.addBills(projectObj.project, projectObj.mainController, std); /* if(canAdd !== null || canAdd !== false){ //插入选中的定额 let addRationDatas = currentLib.type && currentLib.type === libType.elf ? getInsertElfRationData() : getInsertRationData(getCheckedRows()); insertRations(addRationDatas); }*/ if(canAdd === false && $.bootstrapLoading.isLoading()){ $.bootstrapLoading.end(); } }, function () { if($.bootstrapLoading.isLoading()){ $.bootstrapLoading.end(); } }); } } else { let insert = billsLibObj.insertBills(stdBillsJobData, stdBillsFeatureData, node); /*if(insert){ //插入选中的定额 let addRationDatas = currentLib.type && currentLib.type === libType.elf ? getInsertElfRationData() : getInsertRationData(getCheckedRows()); insertRations(addRationDatas); }*/ } } else { node.setExpanded(!node.expanded); //设置展开收起状态 sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items)); renderSheetFunc(args.sheet, function () { let iCount = node.posterityCount(), i, child; for (i = 0; i < iCount; i++) { child = bills.tree.items[args.row + i + 1]; args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea); } args.sheet.invalidateLayout(); }); args.sheet.repaint(); } } } }; //项目指引类型 const itemType = { job: 0, ration: 1 }; const guideItem = { dom: $('#billsGuidance_items'), workBook: null, tree: null, controller: null, treeSetting: { treeCol: 1, emptyRows: 0, headRows: 1, headRowHeight: [40], defaultRowHeight: 21, cols: [ { width: 35, readOnly: false, head: { titleNames: ["选择"], spanCols: [1], spanRows: [1], vAlign: [1], hAlign: [1], font: ["Arial"] }, data: { field: "select", vAlign: 1, hAlign: 1, font: "Arial" } }, { width: 420, readOnly: false, head: { titleNames: ["项目指引"], spanCols: [1], spanRows: [1], vAlign: [1], hAlign: [1], font: ["Arial"] }, data: { field: "name", vAlign: 1, hAlign: 0, font: "Arial" } } ] }, headers: [ {name: '选择', dataCode: 'select', width: 35, vAlign: 'center', hAlign: 'center', formatter: '@'}, {name: '项目指引', dataCode: 'name', width: 300, vAlign: 'center', hAlign: 'left', formatter: '@'}, ], events: { EditStarting: function (sender, args) { if(!bills.tree || guideItem.headers[args.col]['dataCode'] === 'name'){ args.cancel = true; } }, ButtonClicked: function (sender, args) { if(args.sheet.isEditing()){ args.sheet.endEdit(true); } refreshInsertRation(); }, CellDoubleClick: function (sender, args) { if(!bills.tree || !bills.tree.selected){ return; } let node = bills.tree.selected.guidance.tree.selected; if(!node){ return; } if(node.children.length === 0){ if(guideItem.headers[args.col]['dataCode'] === 'name'){ insertRations(getInsertRationData([args.row])); } } else { node.setExpanded(!node.expanded); renderSheetFunc(args.sheet, function () { let iCount = node.posterityCount(), i, child; for (i = 0; i < iCount; i++) { child = bills.tree.selected.guidance.tree.items[args.row + i + 1]; args.sheet.setRowVisible(args.row + i + 1, child.visible, args.sheetArea); } args.sheet.invalidateLayout(); }); args.sheet.repaint(); } } } }; const elfItem = { dom: $('#billsGuidance_items'), workBook: null, tree: null, controller: null, treeSetting: { treeCol: 0, emptyRows: 0, headRows: 1, headRowHeight: [40], defaultRowHeight: 21, cols: [ { width: 250, readOnly: true, head: { titleNames: ["施工工序"], spanCols: [1], spanRows: [1], vAlign: [1], hAlign: [1], font: ["Arial"] }, data: { field: "name", vAlign: 1, hAlign: 0, font: "Arial" } }, { width: 250, readOnly: false, head: { titleNames: ["选项"], spanCols: [1], spanRows: [1], vAlign: [1], hAlign: [1], font: ["Arial"] }, data: { field: "options", vAlign: 1, hAlign: 0, font: "Arial" } } ] }, headers: [ {name: '施工工序', dataCode: 'name', width: 250, rateWidth: 0.5, vAlign: 'center', hAlign: 'center', formatter: '@'}, {name: '选项', dataCode: 'options', width: 250, rateWidth: 0.5, vAlign: 'center', hAlign: 'left', formatter: '@'}, ], events: { CellClick: function (sender, args) { if(elfItem.headers[args.col]['dataCode'] === 'options' && args.sheetArea === 3){ if(!args.sheet.getCell(args.row, args.col).locked() && !args.sheet.isEditing()){ args.sheet.startEdit(); } } }, ClipboardPasting: function (sender, info) { info.cancel = true; } } }; 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; for(let event in events){ workBook.bind(Events[event], events[event]); } } //根据宽度比例设置列宽 //@param {Object}workBook {Number}workBookWidth {Array}headers @return {void} function setColumnWidthByRate(workBook, workBookWidth, headers) { if(workBook){ const sheet = workBook.getActiveSheet(); sheet.suspendEvent(); sheet.suspendPaint(); for(let col = 0; col < headers.length; col++){ if(headers[col]['rateWidth'] !== undefined && headers[col]['rateWidth'] !== null && headers[col]['rateWidth'] !== ''){ let width = workBookWidth * headers[col]['rateWidth']; if(headers[col]['dataCode'] === 'options'){ width = width - 70; } sheet.setColumnWidth(col, width, GC.Spread.Sheets.SheetArea.colHeader) } else { if(headers[col]['headerWidth'] !== undefined && headers[col]['headerWidth'] !== null && headers[col]['headerWidth'] !== ''){ sheet.setColumnWidth(col, headers[col]['headerWidth'], GC.Spread.Sheets.SheetArea.colHeader) } } } sheet.resumeEvent(); sheet.resumePaint(); } } //建表 //@param {Object}module @return {void} function buildSheet(module) { if(!module.workBook){ module.workBook = new GC.Spread.Sheets.Workbook(module.dom[0], {sheetCount: 1}); sheetCommonObj.spreadDefaultStyle(module.workBook); let sheet = module.workBook.getActiveSheet(); if(module === bills){ //默认初始可控制焦点在清单表中 module.workBook.focus(); sheet.options.isProtected = true; sheet.name('stdBillsGuidance_bills'); //设置悬浮提示 TREE_SHEET_HELPER.initSetting(bills.dom[0], bills.treeSetting); } if(module === guideItem){ sheet.options.isProtected = true; sheet.getRange(-1, 0, -1, 1).locked(false); sheet.getRange(-1, 1, -1, 1).locked(true); } if(module === elfItem){ sheet.options.isProtected = true; sheet.getRange(-1, 0, -1, 1).locked(true); sheet.getRange(-1, 1, -1, 1).locked(false); } setOptions(module.workBook, options); buildHeader(module.workBook.getActiveSheet(), module.headers); if(module === elfItem){ setColumnWidthByRate(elfItem.workBook, $('#zy').width(), elfItem.headers) } bindEvent(module.workBook, module.events); } } //清空表数据 //@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 {Array}modules @return {void} function initWorkBooks(modules){ for(let module of modules){ buildSheet(module); } } //初始化并输出树 //@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, false); module.tree.loadDatas(datas); if(module === bills){ initExpandStat(); } module.controller.showTreeData(); if(module === bills){ setBillsHint(bills.tree.items, stdBillsJobData, stdBillsFeatureData); } } //项目指引表焦点控制 //@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; } } } //清单精灵表焦点控制 //@param {Number}row @return {void} function elfItemInitSel(row){ let billsNode = bills.tree.selected; let node = null; if(billsNode && billsNode.elf.tree){ node = billsNode.elf.tree.items[row]; if(node){ billsNode.elf.tree.selected = node; } } } //根据项目指引的类型设置单元格类型,定额类型的项目指引为复选框 //@param {Array}nodes @return {void} function setItemCellType(nodes){ //设置单元格类型 const base = new GC.Spread.Sheets.CellTypes.Base(); const checkBox = new GC.Spread.Sheets.CellTypes.CheckBox(); const sheet = guideItem.workBook.getActiveSheet(); renderSheetFunc(sheet, function(){ for(let node of nodes){ sheet.setCellType(node.serialNo(), 0, node.data.type === itemType.ration ? checkBox : base); } }); } //清单表焦点控制 //@param {Number}row @return {void} function billsInitSel(row){ if(currentLib.type && currentLib.type === libType.elf){ billsSelElf(row); }else { billsSelGuidance(row); } } //清单焦点变换-清单指引操作 //@param {Number}row @return {void} function billsSelGuidance(row){ let guideSheet = guideItem.workBook.getActiveSheet(); cleanData(guideSheet, guideItem.headers, -1); if(!bills.tree){ return; } let node = bills.tree.items[row]; if(!node){ return; } bills.tree.selected = node; refreshInsertRation(); if(!node.guidance.tree){ CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: libSel.val(), billsID: node.getID()}, function (rstData) { initTree(node.guidance, guideSheet, guideItem.treeSetting, rstData); setItemCellType(node.guidance.tree.items); //项目指引初始焦点 guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0); }); } else{ node.guidance.controller.showTreeData(); setItemCellType(node.guidance.tree.items); //项目指引初始焦点 guideItemInitSel(guideSheet.getActiveRowIndex() ? guideSheet.getActiveRowIndex() : 0); } } //清单焦点变换-清单精灵操作 //@param {Number}row @return {void} function billsSelElf(row) { let elfSheet = elfItem.workBook.getActiveSheet(); cleanData(elfSheet, elfItem.headers, -1); if(!bills.tree){ return; } let node = bills.tree.items[row]; if(!node){ return; } bills.tree.selected = node; if(!node.elf.tree){ CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: libSel.val(), billsID: node.getID()}, function (rstData) { //定额数据删除编号信息 for(let rData of rstData){ if(rData.type === itemType.ration){ let nameArr = rData.name.split(' '); if(nameArr.length > 0){ nameArr.splice(0, 1); rData.name = nameArr.join(' '); } } } node.elf.datas = rstData; //第一层节点数据 let firstLevelDatas = _.filter(rstData, function (data) { return data.ParentID == -1; }); //第一层初始数据的选项显示 for(let fData of firstLevelDatas){ let options = getOptions(fData, rstData); fData.options = options.length > 0 ? options[0].name : ''; //下挂的选项 fData.optionsData = options && options.length > 0 ? _.cloneDeep(options) : []; fData.optionChecked = options && options.length > 0 ? [_.cloneDeep(options[0])] : []; } renderSheetFunc(elfSheet, function () { initTree(node.elf, elfSheet, elfItem.treeSetting, firstLevelDatas); //初始选择选项 let initOptsOpr = []; for(let elfNode of node.elf.tree.items){ if(elfNode.data.optionsData.length > 0){ initOptsOpr.push({node: elfNode, data: elfNode.data.optionsData[0]}); } } for(let opr of initOptsOpr){ insertNodeByData(opr.node, opr.data); } TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.elf.tree.items, false); setOptionsCellType(node.elf.tree.items); //项目指引初始焦点 elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0); refreshInsertRation(); }); }); } else{ renderSheetFunc(elfSheet, function () { node.elf.controller.showTreeData(); setOptionsCellType(node.elf.tree.items); //项目指引初始焦点 elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0); refreshInsertRation(); }); } } //获取选项的深度 //@param {Object}opt {Array}options(当前清单所有选项) @return {Array} function getOptionDepth(opt, options) { let parent = _.find(options, {ID: opt.ParentID}); let depth = 0; while (parent){ depth++; parent = _.find(options, {ID: parent.ParentID}); } return depth; } //获取施工工序含有的选项(即当前施工工序的子项),获取的顺序按照NextSiblingID排序 //@param {Object}process {Array}datas @return {Array} function getOptions(process, datas) { let rst = []; if(!process || !process.ID){ return []; } let options = _.filter(datas, function (data) { return data.ParentID == process.ID; }); if(options.length === 0){ return []; } //根据NextSiblingID排序 let IDMapping = {}; for(let opt of options){ IDMapping[opt.ID] = {self: opt, next: null, pre: null}; } for(let opt of options){ let next = IDMapping[opt.NextSiblingID] ? IDMapping[opt.NextSiblingID] : null; if(next){ next.pre = IDMapping[opt.ID]; IDMapping[opt.ID]['next'] = next; } } let first = null, rank = 0; for(let ID in IDMapping){ let obj = IDMapping[ID]; if(!obj.pre){ first = obj; } } while(first){ rank++; first.self.rank = rank; rst.push(first.self); first = first.next; } return rst; } //设置清单精灵选项单元格 //@param {Array}nodes @return {void} function setOptionsCellType(nodes) { let elfSheet = elfItem.workBook.getActiveSheet(); for(let node of nodes){ if(node.data.optionsData && node.data.optionsData.length > 0){ elfSheet.getCell(node.serialNo(), 1).locked(false).cellType(getOptionsCellType()); } else { elfSheet.getCell(node.serialNo(), 1).locked(true).cellType(new GC.Spread.Sheets.CellTypes.Base()); } } } //递归插入节点:原始项目指引数据奇数层为需要插入的节点,偶数层为下拉选项 //@param {Object}node(当前操作的节点) {Object}data(选项) @return {void} function insertNodeByData(node, data) { let elfSheet = elfItem.workBook.getActiveSheet(); let sameDepthNodes = node.children; let insertNextSiblingID = -1, insertParentID = node.data.ID; //当前操作节点的选项 let nodeOpts = getOptions(node.data, bills.tree.selected.elf.datas); let subOpts = getOptions(data, bills.tree.selected.elf.datas); let dataDepth = getOptionDepth(data, bills.tree.selected.elf.datas); if(subOpts.length >0 && subOpts[0].type !== itemType.ration){ if((dataDepth + 1) % 2 === 0){ //排序后的数据 let dataWithRank = _.find(nodeOpts, {ID: data.ID}); //确定插入位置 for(let subOpt of subOpts){ for(let subNode of sameDepthNodes){ //同层节点原本选项数据 let subNodeOptData = _.find(bills.tree.selected.elf.datas, {ID: subNode.data.ID}); //同层节点原本父选项数据 let subNodeOptParent = _.find(bills.tree.selected.elf.datas, {ID: subNodeOptData.ParentID}); let subNodeOptParentWithRank = _.find(nodeOpts, {ID: subNodeOptParent.ID}); //父项顺序决定插入位置 if(dataWithRank.rank < subNodeOptParentWithRank.rank){ insertNextSiblingID = subNode.data.ID; break; } //父项顺序相同,根据子项顺序决定插入位置 else if(dataWithRank.rank = subNodeOptParentWithRank.rank){ if(subOpt.rank < subNode.data.rank){ insertNextSiblingID = subNode.data.ID; break; } } } let sub2Opts = getOptions(subOpt, bills.tree.selected.elf.datas); subOpt.options = sub2Opts.length > 0 ? sub2Opts[0].name : ''; let cloneOpt = _.cloneDeep(subOpt);//不改变原本的数据,比如ParentID cloneOpt.optionChecked = sub2Opts.length > 0 ? [_.cloneDeep(sub2Opts[0])] : []; cloneOpt.optionsData = sub2Opts.length > 0 ? _.cloneDeep(sub2Opts) : []; let newNode = node.tree.insertByData(cloneOpt, insertParentID, insertNextSiblingID); elfSheet.addRows(newNode.serialNo(), 1); node.tree.selected = newNode; elfSheet.setSelection(newNode.serialNo(), elfSheet.getSelections()[0].col, 1, 1); if(sub2Opts.length > 0 && sub2Opts[0].type !== itemType.ration){ insertNodeByData(newNode, sub2Opts[0]); } } } else { insertNodeByData(node, subOpts[0]); } } } //获取选项下拉多选单元格 //@param {void} @return {void} function getOptionsCellType() { let me = this; let elfSheet= elfItem.workBook.getActiveSheet(); function OptionsCellType() { this.isEscKey=false; this.displayText=''; } /* function getHtml(node, cellRect, cellStyle, top) { if(!node){ return ''; } let height = cellRect.height; top = top.replace('px', ''); let htmlArr = []; let options = getOptions(node.data, bills.tree.selected.elf.datas); //let optionsTitle = node.data.options.split(';').join('\n'); htmlArr.push(`
${node.data.options}
`); for(let opt of options){ htmlArr.push(`
${opt.name ? opt.name : ''}
`); } htmlArr.push(`
`); return htmlArr.join(''); }*/ function setOptionsDiv($editor, node, cellRect, cellStyle, top) { if(!node){ return ''; } let height = cellRect.height; top = top.replace('px', ''); let options = getOptions(node.data, bills.tree.selected.elf.datas); let $editInput = $(`
${node.data.options}
`), $optDiv = $(`
`); for(let opt of options){ let $opt = $(`
`), $optInput = $(``); $opt.text(`${opt.name ? opt.name : ''}`); $opt.prepend($optInput); $optDiv.append($opt); //选项复选框点击监听 $optInput.click(function () { //单选 if(billsGuidanceSelMode === 0){ let $allInput = $optDiv.find('input'); for(let input of $allInput){ $(input).prop('checked', false); } $(this).prop('checked', 'checked'); } else {//多选 } }); } $editor.append($editInput); $editor.append($optDiv); } //选择后处理 function doAfterSel(node) { let checkedSels = $('.elf-options').find('input:checked'); let checkedNameArr = [], optionChecked= []; for(let checkSel of checkedSels){ let opt = _.cloneDeep(_.find(bills.tree.selected.elf.datas, {ID: $(checkSel).val()})); opt.rank = $(checkSel).attr('rank'); checkedNameArr.push(opt.name); optionChecked.push(opt); } this.displayText = checkedNameArr.length > 0 ? checkedNameArr.join(';') : ''; node.data.options = this.displayText; node.data.optionChecked = optionChecked; //删除节点 let deleteNodes = getDeleteNodes(node, optionChecked); for(let dNode of deleteNodes){ elfSheet.deleteRows(dNode.serialNo(), dNode.posterityCount() + 1); node.tree.delete(dNode); } //插入节点 for(let perCheked of optionChecked){ let exist = false; let subOpts = getOptions(perCheked, bills.tree.selected.elf.datas); for(let subNode of node.children){ for(let subOpt of subOpts){ if(subNode.data.ID === subOpt.ID){ exist = true; break; } } } //不重复且不为定额时插入 if(!exist && perCheked.type !== itemType.ration){ insertNodeByData(node, perCheked);//这里递归,默认第一个 } } TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.tree.items, false); setOptionsCellType(node.tree.items); refreshInsertRation(); } //获取删除节点 function getDeleteNodes(node, optionChecked) { let rst = []; for(let subNode of node.children){ let exist = false; for(let perChecked of optionChecked){ let subOpts = getOptions(perChecked, bills.tree.selected.elf.datas); for(let subOpt of subOpts){ if(subNode.data.ID === subOpt.ID){ exist = true; break; } } } if(!exist){ rst.push(subNode); } } return rst; } OptionsCellType.prototype = new GC.Spread.Sheets.CellTypes.Base(); OptionsCellType.prototype.createEditorElement = function (context) { let element = document.createElement("div");//这里创建的,会自动销毁 return element }; OptionsCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) { if (editorContext) { let $editor = $(editorContext); $editor.css("position", "fixed"); $editor.css("background", "white"); $editor.css("width", cellRect.width); $editor.attr("gcUIElement", "gcEditingInput"); let activeCellTop = $editor.parent().parent().css('top'); let node = bills.tree.selected.elf.tree.items[elfSheet.getActiveRowIndex()]; setOptionsDiv($editor, node, cellRect, cellStyle, activeCellTop); this.isEscKey = false; } } OptionsCellType.prototype.deactivateEditor = function (editorContext, context) { }; OptionsCellType.prototype.setEditorValue = function (editor, value, context) { this.displayText = value; }; OptionsCellType.prototype.getEditorValue = function (editor, context) { let me = this; let node = bills.tree.selected.elf.tree.items[elfSheet.getActiveRowIndex()]; if(this.isEscKey !=true){ renderSheetFunc(elfSheet, function () { doAfterSel.call(me, node); }); } this.isEscKey = false; return this.displayText; }; OptionsCellType.prototype.updateEditor = function (editorContext, cellStyle, cellRect, context) { }; OptionsCellType.prototype.isReservedKey = function (e, context) { //cell type handle tab key by itself this.isEscKey = e.keyCode === GC.Spread.Commands.Key.esc; return false; }; /* OptionsCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) { if(style.backColor){ ctx.fillStyle = style.backColor; ctx.fillRect(x, y, w, h); ctx.save(); } //边长 const l = 7; let leftPointX = x + w - 15, rightPointX = leftPointX + l, middlePointX = (leftPointX + rightPointX)/2; const cos30 = Math.cos(2*Math.PI * 30 / 360); let hL = l * cos30; let beginY = y + h/2 - hL; ctx.beginPath(); ctx.moveTo(leftPointX, beginY); ctx.lineTo(rightPointX, beginY); ctx.lineTo(middlePointX, beginY + hL); ctx.fillStyle = 'black'; ctx.fill(); ctx.save(); };*/ // override getHitInfo to allow cell type get mouse messages OptionsCellType.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 }; }; return new OptionsCellType(); } //初始化清单的工作内容和项目特征 //@param {Number}billsLibId {Function}callback @return {void} function initJobAndCharacter(billsLibId, callback){ CommonAjax.post('/stdBillsEditor/getJobContent', {userId: userID, billsLibId: billsLibId}, function (datas) { stdBillsJobData = datas; CommonAjax.post('/stdBillsEditor/getItemCharacter', {userId: userID, billsLibId: billsLibId}, function (datas) { stdBillsFeatureData = datas; if(callback){ callback(); } }); }); } //初始化清单展开收起状态 //@return {void} function initExpandStat(){ //读取展开收起状态 let currentExpState = sessionStorage.getItem('stdBillsGuidanceExpState'); if(currentExpState){ bills.tree.setExpandedByState(bills.tree.items, currentExpState); } //非叶子节点默认收起 else{ bills.tree.setRootExpanded(bills.tree.roots, false); } } //设置tag以悬浮提示 function setTagForHint(nodes){ let sheet = bills.workBook.getActiveSheet(); renderSheetFunc(sheet, function () { for(let node of nodes){ sheet.setTag(node.serialNo(), 2, node.data.ruleText ? node.data.ruleText : ''); } }); } //根据编码定位至清单精灵库中 //@param {String}code @return {void} function locateAtBills(code) { let nineCode = code.substring(0, 9); let items = bills.tree.items; let locateBills = _.find(items, function(item){ return item.data.code === nineCode; }); if(locateBills){ expandSearchNodes([locateBills]); sessionStorage.setItem('stdBillsGuidanceExpState', bills.tree.getExpState(bills.tree.items)); } let sheet = bills.workBook.getActiveSheet(); let locateRow = locateBills ? locateBills.serialNo() : 0; sheet.setActiveCell(locateRow, 0); billsInitSel(locateRow); sheet.showRow(locateRow, GC.Spread.Sheets.VerticalPosition.center); } //清单设置悬浮提示信息 //@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}libID @return {void} function libInitSel(libID){ //获取清单 $.bootstrapLoading.start(); CommonAjax.post('/billsGuidance/api/getLibWithBills', {libID: libID}, function(rstData){ currentLib = rstData.guidanceLib; if(guideItem.workBook){ guideItem.workBook.destroy(); guideItem.workBook = null; } if(elfItem.workBook){ elfItem.workBook.destroy(); elfItem.workBook = null; } initViews(); let callback = function () { initTree(bills, bills.workBook.getActiveSheet(), bills.treeSetting, rstData.bills); //清单精灵 if(rstData.guidanceLib.type && rstData.guidanceLib.type == libType.elf){ $('#stdBillsGuidanceTab').text('清单精灵'); //每一个清单节点下挂载一棵清单精灵树 for(let node of bills.tree.items){ node.elf = {tree: null, controller: null, datas: []}; //挂载全部数据,数据不一定全成为树节点 } } //清单指引 else { $('#stdBillsGuidanceTab').text('清单指引'); //每一棵项目指引树挂在清单节点上 for(let node of bills.tree.items){ node.guidance = {tree: null, controller: null}; } } //setTagForHint(bills.tree.items); //默认初始节点 billsInitSel(0); if(doAfterLoadGuidance){ doAfterLoadGuidance(); } $.bootstrapLoading.end(); }; //获取清单库中的工作内容和项目特征 initJobAndCharacter(rstData.guidanceLib.billsLibId, callback); }, function () { $.bootstrapLoading.end(); }); } //初始化清单指引库 //@param {Array}libDats @return {void} function initLibs(libDatas){ libSel.empty(); if(!libDatas){ return; } let selectedLib = sessionStorage.getItem('stdBillsGuidance'); for(let libData of libDatas){ let opt = $('