/** * Created by Zhong on 2017/10/30. */ let gcTree = null; let decDate = null;//恢复后的名称后缀(时间+恢复) //恢复路径t = tender, e = engineering, p = project const recPath = {t: 'T', t_e: 'T_E', t_e_p: 'T_E_P', e: 'E', e_p: 'E_P', p: 'P'}; const gcTreeObj = { tree: null, workBook: null, setting: { tree: { id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: false }, header: [ {name: '工程列表', dataCode: 'name', width: 0.5, rateWidth: 0.5, vAlign: 'center', hAlign: 'left'}, {name: '删除日期', dataCode: 'deleteDateTime', width: 0.1, rateWidth: 0.1, vAlign: 'center', hAlign: 'left'}, {name: '创建日期', dataCode: 'createDateTime', width: 0.1, rateWidth: 0.1, vAlign: 'center', hAlign: 'left'}, {name: '恢复', dataCode: 'recovery', width: 0.05, rateWidth: 0.05, vAlign: 'center', hAlign: 'left'}, {name: '彻底删除', dataCode: 'delete', width: 0.05, rateWidth: 0.05, vAlign: 'center', hAlign: 'left'}, {name: '单价文件', dataCode: 'unitPriceFile', width: 0.05, rateWidth: 0.05, vAlign: 'center', hAlign: 'left'}, {name: '单价文件-清除', dataCode: 'unitPriceFile_delete', width: 0.05, rateWidth: 0.05, vAlign: 'center', hAlign: 'left'}, {name: '费率文件', dataCode: 'feeRateFile', width: 0.05, rateWidth: 0.05, vAlign: 'center', hAlign: 'left'}, {name: '费率文件-清除', dataCode: 'feeRateFile_delete', width: 0.05, rateWidth: 0.05, vAlign: 'center', hAlign: 'left'} ], //恢复和彻底删除字体色 style: { recForeColor: '#007bff', delForeColor: '#dc3545' }, options: { tabStripVisible: false, allowContextMenu: false, allowCopyPasteExcelStyle : false, allowExtendPasteRange: false, allowUserDragDrop : false, allowUserDragFill: false, scrollbarMaxAlign : true } }, renderSheetFuc: function (sheet, fuc) { sheet.suspendPaint(); sheet.suspendEvent(); fuc(); sheet.resumePaint(); sheet.resumeEvent(); }, setOptions: function (workbook, opts) { for(let opt in opts){ workbook.options[opt] = opts[opt]; } }, bindEvent: function (workBook) { const _events = GC.Spread.Sheets.Events; let sheet = workBook.getActiveSheet(); //改变选中节点set selected sheet.bind(_events.SelectionChanging, this.onSelectionChanging); }, buildHeader: function (sheet, headers) { let me = this; let fuc = function () { sheet.options.isProtected = true; sheet.options.protectionOptions = { allowResizeRows: true, allowResizeColumns: true }; let workBookWidth = getWorkBookWidth(); sheet.setColumnCount(headers.length); sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader); for(let i = 0, len = headers.length; i < len; i++){ sheet.setColumnWidth(i, workBookWidth * headers[i].width, GC.Spread.Sheets.SheetArea.colHeader); if(headers[i].dataCode === 'unitPriceFile' || headers[i].dataCode === 'feeRateFile'){ //合并列 sheet.addSpan(0, i, 1, 2, GC.Spread.Sheets.SheetArea.colHeader); } if(headers[i].dataCode === 'unitPriceFile_delete' || headers[i].dataCode === 'feeRateFile_delete'){ continue; } sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader); } }; me.renderSheetFuc(sheet, fuc); }, buildSheet: function () { if(!this.workBook){ this.workBook = new GC.Spread.Sheets.Workbook($('#gcSpread')[0], {sheetCount: 1}); sheetCommonObj.spreadDefaultStyle(this.workBook); this.setOptions(this.workBook, this.setting.options); this.buildHeader(this.workBook.getActiveSheet(), this.setting.header); this.bindEvent(this.workBook); } }, getSelStyle: function (backColor) { let style = new GC.Spread.Sheets.Style(); style.backColor = backColor; 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); return style; }, //设置选中行底色 setSelStyle: function (sel, backColor) { let me = this; let sheet = me.workBook.getSheet(0); me.renderSheetFuc(sheet, function () { let style = me.getSelStyle(backColor); /*sel.row = sel.row === -1 ? 0 : sel.row;*/ for(let i = 0; i < sel.rowCount; i++){ let row = i + sel.row; sheet.setStyle(row, -1, style); } }); }, initSelection: function (newSel, oldSel = null) { let me = this; let node = me.tree.items[newSel.row]; me.tree.selected = node; //恢复底色 if(oldSel){ me.setSelStyle(oldSel, projTreeObj.setting.style.defalutBackColor); } //设置选中行底色 if(newSel){ me.setSelStyle(newSel, projTreeObj.setting.style.selectedColor); } }, onSelectionChanging: function (sender, args) { let me = gcTreeObj; me.initSelection(args.newSelections[0], args.oldSelections[0]); }, //点击恢复列,弹出恢复项目窗口 oprProj: function (modalId, node) { let tenderNodes = m_getTenders(node); let type = modalId === '#rePoj' ? 'recovery' : 'delete'; $(`${modalId} .modal-header`).empty(); $('p', `${modalId} .modal-body`).remove(); $(`${modalId} .modal-header`).html(v_getTitle(type, node)); $(`${modalId} .modal-body`).html(v_getMoBody(type, node, tenderNodes)); $(`${modalId}`).modal('show'); }, //点击单价文件恢复,弹出恢复单价文件窗口 recoveryUnitPrc: function (node) { let unitPriceFiles = node.data.unitPriceFiles; let tenders = m_getTenders(node); $('#reFile h5').text('恢复单价文件'); $('tr', '#reFile tbody').remove(); $('#reFile tbody').html(v_getFiles(fileType.unitPriceFile, unitPriceFiles, tenders, 'recovery')); $('#reFile').modal('show'); }, recoveryFeeRate: function (node) { let feeRateFiles = node.data.feeRateFiles; let tenders = m_getTenders(node); $('#reFile h5').text('恢复费率文件'); $('tr', '#reFile tbody').remove(); $('#reFile tbody').html(v_getFiles(fileType.feeRateFile, feeRateFiles, tenders, 'recovery')); $('#reFile').modal('show'); }, //点击单价文件清除,弹出清除单价文件窗口 deleteUnitPrc: function (node) { let unitPriceFiles = node.data.unitPriceFiles; let tenders = m_getTenders(node); $('#delFile h5').text('彻底删除单价文件'); $('tr', '#delFile tbody').remove(); $('#delFile tbody').html(v_getFiles(fileType.unitPriceFile, unitPriceFiles, tenders, 'delete')); $('#delFile').modal('show'); }, deleteFeeRate: function (node) { let feeRateFiles = node.data.feeRateFiles; let tenders = m_getTenders(node); $('#delFile h5').text('彻底删除费率文件'); $('tr', '#delFile tbody').remove(); $('#delFile tbody').html(v_getFiles(fileType.feeRateFile, feeRateFiles, tenders, 'delete')); $('#delFile').modal('show'); }, getTreeNodeCell: function (tree) { let indent = 20; let levelIndent = -5; let halfBoxLength = 5; let halfExpandLength = 3; let imgWidth = 18; let imgHeight = 14; let TreeNodeCellType = function () { }; TreeNodeCellType.prototype = new GC.Spread.Sheets.CellTypes.Text(); TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) { if (style.backColor) { ctx.save(); ctx.fillStyle = style.backColor; ctx.fillRect(x, y, w, h); ctx.restore(); } else { ctx.clearRect(x, y, w, h); } let drawLine = function (canvas, x1, y1, x2, y2, color) { ctx.save(); ctx.translate(0.5, 0.5); ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.strokeStyle = color; ctx.stroke(); ctx.restore(); }; let drawExpandBox = function (ctx, x, y, w, h, centerX, centerY, expanded) { let rect = {}, h1, h2, offset = 1; rect.top = centerY - halfBoxLength; rect.bottom = centerY + halfBoxLength; rect.left = centerX - halfBoxLength; rect.right = centerX + halfBoxLength; if (rect.left < x + w) { rect.right = Math.min(rect.right, x + w); ctx.save(); ctx.translate(0.5, 0.5); ctx.strokeStyle = 'black'; ctx.beginPath(); ctx.moveTo(rect.left, rect.top); ctx.lineTo(rect.left, rect.bottom); ctx.lineTo(rect.right, rect.bottom); ctx.lineTo(rect.right, rect.top); ctx.lineTo(rect.left, rect.top); ctx.stroke(); ctx.fillStyle = 'white'; ctx.fill(); ctx.restore(); // Draw Horizontal Line h1 = centerX - halfExpandLength; h2 = Math.min(centerX + halfExpandLength, x + w); if (h2 > h1) { drawLine(ctx, h1, centerY, h2, centerY, 'black'); } // Draw Vertical Line if (!expanded && (centerX < x + w)) { drawLine(ctx, centerX, centerY - halfExpandLength, centerX, centerY + halfExpandLength, 'black'); } } } let node = tree.items[options.row]; let showTreeLine = true; if (!node) { return; } let centerX = Math.floor(x) + node.depth() * indent + node.depth() * levelIndent + indent / 2; let x1 = centerX + indent / 2; let centerY = Math.floor((y + (y + h)) / 2); let y1; // Draw Sibling Line const lineColor = '#ababab'; if (showTreeLine) { // Draw Horizontal Line if (centerX < x + w) { drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, lineColor); let img; if(node.data.projType === projectType.folder){ img = document.getElementById('folder_open_pic'); imgWidth = 15; } else if(node.data.projType === projectType.project){ img = document.getElementById('proj_pic'); imgWidth = 18; } else if(node.data.projType === projectType.engineering){ img = document.getElementById('eng_pic'); imgWidth = 14; } else if(node.data.projType === projectType.tender){ img = document.getElementById('tender_pic'); imgWidth = 14; } ctx.drawImage(img, centerX+indent/2+3, centerY - 7, imgWidth,imgHeight); } // Draw Vertical Line if (centerX < x + w) { y1 = node.isLast() ? centerY : y + h; if (node.isFirst() && !node.parent.parent) { drawLine(ctx, centerX, centerY, centerX, y1, lineColor); } else { drawLine(ctx, centerX, y, centerX, y1, lineColor); } } } // Draw Expand Box if (node.children.length > 0) { drawExpandBox(ctx, x, y, w, h, centerX, centerY, node.expanded); } // Draw Parent Line if (showTreeLine) { var parent = node.parent, parentCenterX = centerX - indent - levelIndent; while (parent.parent) { if (!parent.isLast()) { if (parentCenterX < x + w) { drawLine(ctx, parentCenterX, y, parentCenterX, y + h, lineColor); } } parent = parent.parent; parentCenterX -= (indent + levelIndent); } }; // Draw Text //x = x + (node.depth() + 1) * indent + node.depth() * levelIndent; x = x + (node.depth() + 1) * indent + node.depth() * levelIndent + imgWidth + 3; w = w - (node.depth() + 1) * indent - node.depth() * levelIndent - imgWidth - 3; GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments); }; TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) { let info = {x: x, y: y, row: context.row, col: context.col, cellStyle: cellStyle, cellRect: cellRect, sheetArea: context.sheetArea}; let node = tree.items[info.row]; let offset = -1; let centerX = info.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2; let text = context.sheet.getText(info.row, info.col); let value = context.sheet.getValue(info.row, info.col); let acStyle = context.sheet.getActualStyle(info.row, info.col), zoom = context.sheet.zoom(); let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: context.sheet, row: info.row, col: info.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport}); if(info.x > centerX + halfBoxLength && info.x < centerX + halfBoxLength + imgWidth + indent/2+3 + textLength){ info.isReservedLocation = true; } return info; }; TreeNodeCellType.prototype.processMouseDown = function (hitinfo) { let offset = -1; let node = tree.items[hitinfo.row]; tree.selected = node; let centerX = hitinfo.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2; let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;; if (!node || node.children.length === 0) { return; } if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 && hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) { node.setExpanded(!node.expanded); TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () { let iCount = node.posterityCount(), i, child; for (i = 0; i < iCount; i++) { child = tree.items[hitinfo.row + i + 1]; hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.visible, hitinfo.sheetArea); } hitinfo.sheet.invalidateLayout(); }); hitinfo.sheet.repaint(); } }; TreeNodeCellType.prototype.processMouseEnter = function (hitinfo) { let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col); let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col); let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col); let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col), zoom = hitinfo.sheet.zoom(); let node = tree.items[hitinfo.row]; let nodeIndent = node ? (node.depth() + 1) * indent + node.depth() * levelIndent + imgWidth + 3 : 0; let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport}); let cellWidth = hitinfo.sheet.getCell(-1, hitinfo.col).width(); if(textLength > cellWidth - nodeIndent){ TREE_SHEET_HELPER.showTipsDiv(text,{pos: {}},hitinfo); } }; TreeNodeCellType.prototype.processMouseLeave = function (hitinfo) { TREE_SHEET_HELPER.tipDiv = 'hide'; if (TREE_SHEET_HELPER._toolTipElement) { $(TREE_SHEET_HELPER._toolTipElement).hide(); TREE_SHEET_HELPER._toolTipElement = null; }; TREE_SHEET_HELPER.tipDivCheck();//延时检查:当tips正在show的时候,就调用了hide方法,会导致tips一直存在,所以设置一个超时处理 } return new TreeNodeCellType(); }, getBaseCell: function () { let MyBaseCell = function () { }; MyBaseCell.prototype = new GC.Spread.Sheets.CellTypes.Text(); MyBaseCell.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, isReservedLocation: true }; }; MyBaseCell.prototype.processMouseDown = function (hitinfo) { let dataCode = gcTreeObj.setting.header[hitinfo.col]['dataCode']; let node = gcTreeObj.tree.items[hitinfo.row]; let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col); let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col); let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col), zoom = hitinfo.sheet.zoom(); let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport}); if(hitinfo.x - hitinfo.cellRect.x > 0 && hitinfo.x - hitinfo.cellRect.x < textLength){ //恢复 if(dataCode === 'recovery'){ gcTreeObj.oprProj('#rePoj', node); } //清除 else if(dataCode === 'delete'){ gcTreeObj.oprProj('#delPoj', node) } //恢复单价文件 else if(dataCode === 'unitPriceFile'){ gcTreeObj.recoveryUnitPrc(node); } //清除单价文件 else if(dataCode === 'unitPriceFile_delete'){ gcTreeObj.deleteUnitPrc(node); } //恢复费率文件 else if(dataCode === 'feeRateFile'){ gcTreeObj.recoveryFeeRate(node); } //清除费率文件 else if(dataCode === 'feeRateFile_delete'){ gcTreeObj.deleteFeeRate(node); } } }; MyBaseCell.prototype.processMouseMove = function (hitInfo) { let dataCode = gcTreeObj.setting.header[hitInfo.col]['dataCode']; if(dataCode === 'recovery' || dataCode === 'delete' || dataCode === 'unitPriceFile' || dataCode === 'unitPriceFile_delete' || dataCode === 'feeRateFile' || dataCode === 'feeRateFile_delete'){ let sheet = hitInfo.sheet; let div = sheet.getParent().getHost(); let canvasId = div.id + "vp_vp"; let canvas = $(`#${canvasId}`)[0]; //改变鼠标图案 let text = hitInfo.sheet.getText(hitInfo.row, hitInfo.col); let value = hitInfo.sheet.getValue(hitInfo.row, hitInfo.col); let acStyle = hitInfo.sheet.getActualStyle(hitInfo.row, hitInfo.col), zoom = hitInfo.sheet.zoom(); let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitInfo.sheet, row: hitInfo.row, col: hitInfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport}); if (sheet && hitInfo.x - hitInfo.cellRect.x > 0 && hitInfo.x - hitInfo.cellRect.x < textLength) { canvas.style.cursor='pointer'; return true; }else{ canvas.style.cursor='default'; } } return false; }; return new MyBaseCell(); }, setCellValue: function (cell, node) { const sheet = this.workBook.getActiveSheet(); const {row, col} = cell; const dataCode = this.setting.header[col]['dataCode']; let value = ''; if(dataCode === 'deleteDateTime' || dataCode === 'createDateTime'){ if (node.data.projType === projectType.tender && deleted(node)) { let date = dataCode === 'deleteDateTime' ? node.data.deleteInfo.deleteDateTime : node.data.createDateTime; let localDateTime = new Date(date).toLocaleDateString(); value = new Date(localDateTime).Format('yyyy-MM-dd'); } } else if(dataCode === 'recovery'){ if(deleted(node)){ value = '恢复'; } } else if(dataCode === 'delete'){ if(deleted(node)){ value = '彻底删除'; } } else if(dataCode === 'unitPriceFile'){ if(node.data.projType === projectType.project && node.data.unitPriceFiles !== undefined && node.data.unitPriceFiles.length > 0){ value = '恢复'; } } else if(dataCode === 'unitPriceFile_delete'){ if(node.data.projType === projectType.project && node.data.unitPriceFiles !== undefined && node.data.unitPriceFiles.length > 0){ value = '彻底删除'; } } else if(dataCode === 'feeRateFile'){ if(node.data.projType === projectType.project && node.data.feeRateFiles !== undefined && node.data.feeRateFiles.length > 0){ value = '恢复'; } } else if(dataCode === 'feeRateFile_delete'){ if(node.data.projType === projectType.project && node.data.feeRateFiles !== undefined && node.data.feeRateFiles.length > 0){ value = '彻底删除'; } } else { value = node.data[dataCode] ? node.data[dataCode] : ''; } sheet.setValue(row, col, value); }, showTreeData: function (nodes, headers) { let me = this; let sheet = me.workBook.getActiveSheet(); let fuc = function(){ sheet.setRowCount(nodes.length); for(let i = 0; i < nodes.length; i++){ let treeNodeCell = me.getTreeNodeCell(me.tree); sheet.getCell(i, 0).cellType(treeNodeCell); for(let j = 0; j < headers.length; j++){ sheet.getRange(-1, j, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[j]['hAlign']]); sheet.getRange(-1, j, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[j]['vAlign']]); if(j !== 0){ sheet.getCell(i, j).cellType(me.getBaseCell()); } let dataCode = headers[j].dataCode; if(dataCode === 'recovery' || dataCode === 'unitPriceFile' || dataCode === 'feeRateFile'){ let style = new GC.Spread.Sheets.Style(); style.foreColor = me.setting.style.recForeColor; sheet.setStyle(-1, j, style); } else if(dataCode === 'delete' || dataCode === 'unitPriceFile_delete' || dataCode === 'feeRateFile_delete'){ let style = new GC.Spread.Sheets.Style(); style.foreColor = me.setting.style.delForeColor; sheet.setStyle(-1, j, style); } me.setCellValue({row: i, col: j}, nodes[i]); } } }; me.renderSheetFuc(sheet, fuc); }, refreshNodeData: function (node) { let me = this; let sheet = me.workBook.getActiveSheet(); let header = me.setting.header; let rIdx = me.tree.items.indexOf(node); me.renderSheetFuc(sheet, function () { for(let i = 0; i < header.length; i++){ me.setCellValue({row: rIdx, col: i}, node); } }); }, remove: function (node) { let me = this; let sheet = me.workBook.getActiveSheet(); //删除行号 let rIdx = me.tree.items.indexOf(node); //删除行数 let count = node.posterityCount() + 1; me.tree.removeNode(node); me.renderSheetFuc(sheet, function () { sheet.deleteRows(rIdx, count); sheet.setRowCount(me.tree.items.length); me.initSelection({row: sheet.getActiveRowIndex(), rowCount: 1}); }); }, move: function (orgRow, newRow) { this.workBook.getActiveSheet().deleteRows(orgRow, 1); this.addRow(this.tree.items[newRow]); } }; $(document).ready(function () { $('#tab_pm_gc').on('show.bs.tab', function () { //侧滑隐藏 $('.slide-sidebar').removeClass('open'); $('.slide-sidebar').css('width', '0'); gc_init(); if(projTreeObj.workBook){ projTreeObj.workBook.destroy(); projTreeObj.workBook = null; } projTreeObj.tree = null; }); e_recFiles($('#reFileBtn')); e_delFiles($('#delFileBtn')); e_recProj($('#rePojBtn')); e_delProj($('#delPojBtn')); }); function gc_init(){ $.bootstrapLoading.start(); a_getGC(function (datas) { m_buildVirtualTree(datas); let normalDatas = m_VTreeToDatas(datas); gcTreeObj.tree = pmTree.createNew(gcTreeObj.setting, normalDatas); gcTreeObj.tree.selected = gcTreeObj.tree.items[0]; gcTreeObj.buildSheet(); gcTreeObj.showTreeData(gcTreeObj.tree.items, gcTreeObj.setting.header); //初始选择 let initSel = gcTreeObj.workBook.getSheet(0).getSelections()[0] ? gcTreeObj.workBook.getSheet(0).getSelections()[0] : {row: 0, rowCount: 1}; gcTreeObj.initSelection(initSel); autoFlashHeight(); gcTreeObj.workBook.refresh(); }); } //项目恢复模态框标题 function v_getTitle(type, node){ let html = ''; html += type === 'recovery' ? ''; } else if(node.data.projType === projectType.engineering){ html += '单项工程'; } else if(node.data.projType === projectType.tender){ html += '单位工程'; } html += ''; return html; } //项目恢复模态框主体 function v_getMoBody(type, oprNode, nodes){ let html = ''; if(type === 'recovery'){ if(oprNode.data.projType === projectType.tender){ decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)'; let recName = oprNode.data.name + decDate; html += '

恢复后将重命名为 ' + recName + '

'; } else { if(oprNode.data.projType === projectType.project){ html += '

' + oprNode.data.name + '下的单位工程都将恢复,恢复后将重命名为

'; } else if(oprNode.data.projType === projectType.engineering){ html += '

' + oprNode.data.name + '下的单位工程都将恢复,恢复后将重命名为

'; } html += ('

'); for(let i = 0, len = nodes.length; i < len; i++){ let recName = nodes[i].data.name + '(' + new Date().Format('MM-dd hh:mm:ss') +'恢复)'; html += '' + recName + '、'; } html = html.slice(0, html.length - 1); html += ('

'); } html += ('

点“确定”按钮,确认从回收站中恢复。

'); } else{ html += ('

点“确定”按钮,确认彻底删除数据。

'); } return html; } //单价、费率文件恢复弹出框数据 function v_getFiles(type, files, tenders, opr = null){ let html = ''; function hasTheFile(tenders, fileId, fileType){ for(let tender of tenders){ let fileAttr = fileType === 'UnitPriceFile' ? 'unitPriceFile' : 'feeFile'; if(tender.data.property[fileAttr]['id'] == fileId){ return true; } } return false; } for(let i = 0, len = files.length; i < len; i ++){ let recName = type === fileType.unitPriceFile ? files[i].name : files[i].name; let fileId = type === fileType.unitPriceFile ? files[i].id : files[i].ID; let recTimeA = formatDate(new Date(files[i].deleteInfo.deleteDateTime), 'yyyy-MM-dd'); let recTimeB = formatDate(new Date(files[i].deleteInfo.deleteDateTime), 'HH:mm:ss'); if(opr && opr === 'delete'){ //还被引用,不可删除 if(hasTheFile(tenders, fileId, type)){ html += ''+ recName +'' + recTimeA + '
' + recTimeB + ''; } else { html += ''+ recName +'' + recTimeA + '
' + recTimeB + ''; } } else{ html += ''+ recName +'' + recTimeA + '
' + recTimeB + ''; } } return html; } //恢复或清除单价、费率文件后前端显示变化 function v_refreshFiles(project, fileIds, type){ let projFiles; if(type === fileType.unitPriceFile){ projFiles = project.data.unitPriceFiles; } else if(type === fileType.feeRateFile){ projFiles = project.data.feeRateFiles; } if(projFiles && projFiles.length > 0){ let tempFiles = []; for(let i = 0, len = projFiles.length; i < len; i++){ let isExist = false; for(let j = 0, jLen = fileIds.length; j < jLen; j++){ let id = projFiles[i].id || projFiles[i].ID || null; if(id && id === fileIds[j]){ isExist = true; break; } } if(!isExist){ tempFiles.push(projFiles[i]); } } if(type === fileType.unitPriceFile){ project.data.unitPriceFiles = tempFiles; } else if(type === fileType.feeRateFile){ project.data.feeRateFiles = tempFiles; } } } function v_removeNode(node){ gcTreeObj.remove(node); let parent = node.parent || null; if(parent && parent.children.length === 0 && parent.data !== undefined){ if(parent.data.projType === projectType.project && fileEmpty(parent)){ v_removeNode(parent); } else if(parent.data.projType !== projectType.project){ v_removeNode(parent); } } } function v_refreshNode(node, recovery = true){ if(recovery){ if(deleted(node)){ delete node.data.deleteInfo; } } gcTreeObj.refreshNodeData(node); let parent = node.parent || null; if(parent && parent.data !== undefined){ v_refreshNode(parent, recovery); } } //将获取的回收站中的数据建虚拟树 function m_buildVirtualTree(datas){ for(let i = 0, len = datas.length; i < len; i++){ if(datas[i].projType === projectType.project){ datas[i].ParentID = -1; } let children = datas[i].children || null; if(children){ m_buildVirtualTree(children); } let next = datas[i+1] || null; if(next){ datas[i].NextSiblingID = next.ID; } else { datas[i].NextSiblingID = -1; } } } function m_VTreeToDatas(datas){ let rst = []; let projs = datas; rst = rst.concat(projs); for(let i = 0, len = projs.length; i < len; i++){ let p_engs = projs[i].children || null; if(p_engs){ rst = rst.concat(p_engs); for(let j = 0, jLen = p_engs.length; j < jLen; j ++){ let e_tenders = p_engs[j].children || null; if(e_tenders){ rst = rst.concat(e_tenders); } } } } return rst; } //获得当前节点的tenders数据,模态提示框用 function m_getTenders(node){ if(node.data.projType === projectType.tender) return [node]; else { let rst = []; if(node.children.length > 0){ node.children.forEach(function (cNode) { if(cNode.children.length > 0){ cNode.children.forEach(function (ccNode) { if(ccNode.data.projType === projectType.tender) rst.push(ccNode); }); } else if(cNode.children.length === 0 && cNode.data.projType === projectType.tender){ rst.push(cNode); } }); } return rst; } } //获得要更新的数据(包含恢复的数据,维护项目管理树的数据) function m_getRecDatas(oprNode){ let rst = Object.create(null); let rstProj = [], rstFile = []; let path; if(oprNode.data.projType === projectType.tender){ path = recPath.t; let engineering = oprNode.parent || null; if(!engineering) return null; let project = engineering.parent || null; if(!project) return null; if(engineering && deleted(engineering)){ path = recPath.t_e; } //恢复建设项目 if(project && deleted(project)){ path = recPath.t_e_p; } //恢复单价、费率文件 rstFile = rstFile.concat(getUpdateFiles([oprNode], project)); if(path === recPath.t){ rstProj = rstProj.concat(getUpdateDatas(projectType.tender, oprNode, -1, true)); } else if(path === recPath.t_e){ rstProj = rstProj.concat(getUpdateDatas(projectType.tender, oprNode, -1, false)); rstProj = rstProj.concat(getUpdateDatas(projectType.engineering, engineering, -1, true)); } else if(path === recPath.t_e_p){ rstProj = rstProj.concat(getUpdateDatas(projectType.tender, oprNode, -1, false)); rstProj = rstProj.concat(getUpdateDatas(projectType.engineering, engineering, -1, false)); rstProj = rstProj.concat(getUpdateDatas(projectType.project, project, -1, false)); } } else if(oprNode.data.projType === projectType.engineering){ path = recPath.e; let project = oprNode.parent || null; if(!project) return null; //恢复建设项目 if(project && deleted(project)){ path = recPath.e_p; } let tenders = oprNode.children; if(tenders.length > 0){ for(let i = 0, len = tenders.length; i < len; i++){ rstProj = rstProj.concat(getUpdateDatas(projectType.tender, tenders[i], tenders[i].data.NextSiblingID, false)); } rstProj = deWeightName(rstProj); //恢复单价、费率文件 rstFile = rstFile.concat(getUpdateFiles(tenders, project)); } if(path === recPath.e){ rstProj= rstProj.concat(getUpdateDatas(projectType.engineering, oprNode, -1, true)); } else if(path === recPath.e_p){ rstProj= rstProj.concat(getUpdateDatas(projectType.engineering, oprNode, -1, false)); rstProj= rstProj.concat(getUpdateDatas(projectType.project, project, -1, false)); } } else if(oprNode.data.projType === projectType.project){ path = recPath.p; let engineerings = oprNode.children; if(engineerings.length > 0){ let allTenders = [], rstEngs = []; for(let i = 0, len = engineerings.length; i < len; i++){ //恢复单项工程 rstEngs = rstEngs.concat(getUpdateDatas(projectType.engineering, engineerings[i], engineerings[i].data.NextSiblingID, false)); let tenders = engineerings[i].children; allTenders = allTenders.concat(tenders); let rstTends = []; for(let j = 0, jLen = tenders.length; j < jLen; j++){ //恢复单位工程 rstTends = rstTends.concat(getUpdateDatas(projectType.tender, tenders[j], tenders[j].data.NextSiblingID, false)); } //去除重名 rstTends = deWeightName(rstTends); rstProj = rstProj.concat(rstTends); } //去除重名 rstEngs = deWeightName(rstEngs); rstProj = rstProj.concat(rstEngs); //恢复单价、费率文件 rstFile = rstFile.concat(getUpdateFiles(allTenders, oprNode)); } //恢复建设项目 rstProj = rstProj.concat(getUpdateDatas(projectType.project, oprNode, false, false)); } rst.proj = rstProj; rst.file = rstFile; return rst; } //获取清除的数据 function m_getDelDatas(oprNode){ let rst = []; if(!oprNode){ return rst; } function getChild(node){ rst.push({updateType: 'Project', ID: node.data.ID}); if(node.children.length > 0){ for(let child of node.children){ getChild(child); } } } getChild(oprNode); //父节点只有一个单位工程,则清除此单位工程的时候,父节点也清除,(建设项目单价、费率文件存在时不清除) if(oprNode.data.projType === projectType.tender){ let eng = oprNode.parent, proj = null; if(eng && deleted(eng)){ proj = eng.parent; rst.push({updateType: 'Project', ID: eng.data.ID}); } if(proj && deleted(proj) && fileEmpty(proj)){ rst.push({updateType: 'Project', ID: proj.data.ID}) } } else if(oprNode.data.projType === projectType.engineering){ let proj = oprNode.parent; if(proj && deleted(proj) && fileEmpty(proj)){ rst.push({updateType: 'Project', ID: proj.data.ID}); } } else if(oprNode.data.projType === projectType.project){ for(let uf of oprNode.data.unitPriceFiles){ rst.push({updateType: fileType.unitPriceFile, ID: uf.id}); } for(let ff of oprNode.data.feeRateFiles){ rst.push({updateType: fileType.feeRateFile, ID: ff.ID}); } } return rst; } //获得勾选的单价、费率文件的id function m_getFilesObjs(nodes){ let rst = []; for(let i = 0, len = nodes.length; i < len; i++){ let fileId = $(nodes[i]).attr('fileId') || null; if(fileId){ let name = $('td:eq(0)', $(nodes[i])[0].parentNode.parentNode)[0].textContent; if($(nodes[i]).attr('fileType') === fileType.unitPriceFile){ fileId = parseInt(fileId); } let obj = Object.create(null); obj.id = fileId; obj.name = name; rst.push(obj); } } return rst; } function m_project(node){ if(node && node.data.projType === projectType.project) return node; if(!node) return null; let parent = node.parent || null; if(!parent) return null; if(parent && parent.data.projType === projectType.project) return parent; let gParent = parent.parent || null; if(!gParent) return null; if(gParent && gParent.data.projType === projectType.project) return gParent; return null; } //点击单价文件、费率文件下的恢复操作(确认) function e_recFiles(btn){ btn.bind('click', function () { $.bootstrapLoading.start(); decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)'; let recObjs = m_getFilesObjs($('[name = "fileItems"]:checked')); let recIds = []; for(let i of recObjs){ recIds.push(i.id); } let type = $('[name = "fileItems"]:checked').attr('fileType'); let selected = gcTreeObj.tree.selected; //backend let updateDatas = []; for(let i = 0, len = recObjs.length; i < len; i++){ let findData = type === fileType.unitPriceFile ? {id: recObjs[i].id} : {ID: recObjs[i].id}; updateDatas.push(getUpdateObj(type, findData, {deleteInfo: null, name: delPostFix(recObjs[i].name) + decDate})); } let isRecoverProj = false; //恢复建设项目 if(updateDatas.length > 0 && deleted(selected)){ isRecoverProj = true; updateDatas.push(getUpdateObj(projectType.project, {ID: selected.data.ID}, {deleteInfo: null, name: delPostFix(selected.data.name) + decDate})); } updateDatas = deWeightName(updateDatas); a_rec(updateDatas, caller); function caller(){ //front if(recIds.length > 0){ v_refreshFiles(selected, recIds, type); if(deleted(selected)){ delete selected.data.deleteInfo; } if(fileEmpty(selected) && selected.children.length === 0){ gcTreeObj.remove(selected); } else { gcTreeObj.refreshNodeData(selected); } } if (isRecoverProj) { projTreeObj.emitTreeChange(); } } }); } //点击单价、费率文件的清除操作(确认) function e_delFiles(btn){ btn.bind('click', function () { $.bootstrapLoading.start(); let selected = gcTreeObj.tree.selected;//project let delObjs = m_getFilesObjs($('[name = "fileItems"]:checked')); let type = $('[name = "fileItems"]:checked').attr('fileType'); let delDatas = []; let delIds = []; for(let delObj of delObjs){ delIds.push(delObj.id); delDatas.push({updateType: type, ID: delObj.id}); } //此操作造成了建设项目的文件为空,则清除建设项目 if(fileWillEmpty(selected, delIds, type)){ //delDatas.push({updateType: 'Project', ID: selected.data.ID}); } if(delDatas.length > 0){ //backend a_delGC(delDatas, caller); //front function caller(){ v_refreshFiles(selected, delIds, type); if(fileEmpty(selected) && selected.children.length === 0){ gcTreeObj.remove(selected); } else { gcTreeObj.refreshNodeData(selected); } } } }); } //点击项目下的恢复操作(确认) function e_recProj(btn){ btn.bind('click', function () { $.bootstrapLoading.start(); let selected = gcTreeObj.tree.selected; //backend let updateObj = m_getRecDatas(selected); let updateDatas = updateObj.proj.concat(updateObj.file); let fileObj = getRecFileObj(updateObj.file); //保存成功后回调front a_rec(updateDatas, caller); function caller() { let project = m_project(selected); if(project){ if(fileObj[fileType.unitPriceFile].length > 0){ v_refreshFiles(project, fileObj[fileType.unitPriceFile], fileType.unitPriceFile); } if(fileObj[fileType.feeRateFile].length > 0){ v_refreshFiles(project, fileObj[fileType.feeRateFile], fileType.feeRateFile); } } v_removeNode(selected); v_refreshNode(selected, true); projTreeObj.emitTreeChange(); } }); } function e_delProj(btn){ btn.bind('click', function () { $.bootstrapLoading.start(); let selected = gcTreeObj.tree.selected; //backend let delDatas = m_getDelDatas(selected); if(delDatas.length > 0){ a_delGC(delDatas, caller); } //front function caller() { v_removeNode(selected); v_refreshNode(selected, false); } }); } function a_getGC(callback){ CommonAjax.post('/pm/api/getGCDatas', {user_id: userID}, function (rstData) { if(callback){ callback(rstData); } $.bootstrapLoading.end(); }, function () { $.bootstrapLoading.end(); }); } function a_rec(nodes, callback){ CommonAjax.post('/pm/api/recGC', {user_id: userID, nodes: nodes}, function (rstData) { if(callback){ callback(); } $.bootstrapLoading.end(); }, function () { $.bootstrapLoading.end(); }); } function a_delGC(delDatas, callback){ CommonAjax.post('/pm/api/delGC', {user_id: userID, delDatas: delDatas}, function(rstData){ if(callback){ callback(); } $.bootstrapLoading.end(); }, function () { $.bootstrapLoading.end(); }); } //去除重名,回收站不处理重名,只保证恢复到项目管理中不出现重名 function deWeightName(datas){ let rst = []; let _deWeight = Object.create(null), prefix = 'name_'; //按同名分组 for(let i = 0, len = datas.length; i < len; i++){ let data = datas[i]; let _names = _deWeight[prefix + data.updateData.name] || null; if(!_names){ _names = _deWeight[prefix + data.updateData.name] = []; } if(_names){ _names.push(data); } } for(let _name in _deWeight){ let sameNameDatas = _deWeight[_name]; let count = 0; for(let i = 0, len = sameNameDatas.length; i < len; i++){ let postFix = '(' + count + ')'; if(i > 0){ sameNameDatas[i].updateData.name = sameNameDatas[i].updateData.name + postFix; } count ++; rst.push(sameNameDatas[i]); } } return rst; } //去除名称后缀(Date恢复) function delPostFix (str){ let rst = ''; rst = delPostRecFix(delPostNameFix(str)); return rst; } function delPostRecFix (str){ let rst = ''; let re = /(+[0-9]{2}-[0-9]{2}\s+[0-9]{2}:[0-9]{2}:[0-9]{2}恢复)/g; rst = str.replace(re, ''); return rst; } function delPostNameFix (str){ let rst = ''; let re = /(+[0-9][0-9]*)/g; rst = str.replace(re, ''); return rst; } function deleted(node){ return node.data.deleteInfo !== undefined && node.data.deleteInfo && node.data.deleteInfo.deleted; } function fileEmpty(node){ return node.data.unitPriceFiles.length === 0 && node.data.feeRateFiles.length === 0; } function fIsExist(files, id, type){ let isExist = false; for(let i = 0, len = files.length; i < len; i++){ if((type === fileType.unitPriceFile && files[i].id === parseInt(id)) || (type === fileType.feeRateFile && files[i].ID === id)){ isExist = true; break; } } return isExist; } //删除的文件是否会导致建设项目不再存有文件 function fileWillEmpty(proj, delIds, type){ let ufs = proj.data.unitPriceFiles, ffs = proj.data.feeRateFiles; let theFiles = type === fileType.unitPriceFile ? ufs : ffs; otherFiles = type === fileType.unitPriceFile ? ffs : ufs; let uniqIds = Array.from(new Set(delIds)); if(theFiles.length === delIds.length){ for(let id of uniqIds){ if(!fIsExist(theFiles, id, type)){ return false; } } } if(otherFiles.length === 0){ return true; } return false; } function getRecFileObj(files){ let rst = Object.create(null); let rst_UF = [], rst_FF = []; for(let i = 0, len = files.length; i < len; i++){ if(files[i].findData !== undefined){ if(files[i].updateType === fileType.unitPriceFile && files[i].findData.id !== undefined){ rst_UF.push(files[i].findData.id); } else if(files[i].updateType === fileType.feeRateFile && files[i].findData.ID !== undefined){ rst_FF.push(files[i].findData.ID); } } } rst[fileType.unitPriceFile] = rst_UF; rst[fileType.feeRateFile] = rst_FF; return rst; } function getUpdateObj(updateType, findData, updateData){ let obj = Object.create(null); obj.updateType = updateType; obj.findData = findData; obj.updateData = updateData; return obj; } function getUpdateDatas(updateType, node, mtNID, mtPM){ let rst = []; decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)'; let newName = delPostFix(node.data.name) + decDate; if(updateType === projectType.tender || updateType === projectType.engineering){ //维护项目管理树 if(mtPM){ rst.push(getUpdateObj(updateType, {ParentID: node.data.ParentID, NextSiblingID: -1, deleteInfo: null}, {NextSiblingID: node.data.ID})); } //恢复 if(mtNID){ rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {name: newName, deleteInfo: null, NextSiblingID: mtNID})); } else { rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {name: newName, deleteInfo: null})); } } else if(updateType === projectType.project){ //恢复 rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {deleteInfo: null, name: newName}));//NextSibling为undefined,后端处理 } return rst; } //unitPriceFile or feeRateFile function getUpdateFiles(tenders, project){ let rstUF = [], rstFF = [], rst = []; let _unitFiles = Object.create(null), _feeFiles = Object.create(null), prefix = '_id'; decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)'; for(let i = 0, len = tenders.length; i < len; i++){ //恢复单价文件 if(project && project.data.unitPriceFiles.length > 0 && fIsExist(project.data.unitPriceFiles, tenders[i].data.property.unitPriceFile.id, fileType.unitPriceFile)){ //unitFiles.push(tenders[i].data.property.unitPriceFile.id); let propId = tenders[i].data.property.unitPriceFile.id; let propName = tenders[i].data.property.unitPriceFile.name; let _uf = _unitFiles[prefix + propId] || null; if(!_uf){ let obj = Object.create(null); obj.id = parseInt(propId); obj.name = propName; _unitFiles[prefix + propId] = obj; } } //恢复费率文件 if(project && project.data.feeRateFiles.length > 0 && fIsExist(project.data.feeRateFiles, tenders[i].data.property.feeFile.id, fileType.feeRateFile)){ //feeFiles.push(tenders[i].data.property.feeFile.id); let propId = tenders[i].data.property.feeFile.id; let propName = tenders[i].data.property.feeFile.name; let _ff = _feeFiles[prefix + propId] || null; if(!_ff){ let obj = Object.create(null); obj.id = propId; obj.name = propName; _feeFiles[prefix + propId] = obj; } } } for(let uf in _unitFiles){ rstUF.push(getUpdateObj(fileType.unitPriceFile, {id: _unitFiles[uf].id}, {deleteInfo: null, name: delPostFix(_unitFiles[uf].name) + decDate})); } for(let ff in _feeFiles){ rstFF.push(getUpdateObj(fileType.feeRateFile, {ID: _feeFiles[ff].id}, {deleteInfo: null, name: delPostFix(_feeFiles[ff].name) + decDate})); } rst = rst.concat(deWeightName(rstUF)); rst = rst.concat(deWeightName(rstFF)); return rst; }