'use strict'; /** * * * @author Zhong * @date 2018/6/28 * @version */ const pmShare = (function () { const spreadDom = $('#shareSpread'); let shareSeleted = null; let spreadObj = { workBook: null, sheet: null }; let preSelection = null; //项目分享类型,由别人分享给自己的,和自己分享给别人的 const shareType = { receive: 'receive', shareTo: 'shareTo' }; //操作类型 const oprType = { copy: 'copy', cancel: 'cancel' }; let tree = null, actualIDShareInfo = {};//项目真实树ID与项目分享信息映射 const treeCol = 0; const treeSetting = { tree: { id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: false } }; const headers = [ { name: '工程列表', dataCode: 'name', width: 300, rateWidth: 0.55, vAlign: 'center', hAlign: 'left' }, { name: '来自', dataCode: 'from', width: 80, rateWidth: 0.15, vAlign: 'center', hAlign: 'left' }, { name: '分享时间', dataCode: 'shareDate', width: 140, rateWidth: 0.15, vAlign: 'center', hAlign: 'left' }, { name: '总造价', dataCode: 'totalCost', width: 100, vAlign: 'center', hAlign: 'right', formatter: '0.00' }, { name: '项目类别', dataCode: 'valuationType', width: 100, vAlign: 'center', hAlign: 'left' }, ]; const spreadOpts = { workBook: { tabStripVisible: false, allowContextMenu: false, allowCopyPasteExcelStyle: false, allowExtendPasteRange: false, allowUserDragDrop: false, allowUserDragFill: false, scrollbarMaxAlign: true }, sheet: { isProtected: true, frozenlineColor: '#ababab', protectionOptions: { allowResizeRows: true, allowResizeColumns: true }, clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values } }; const spreadEvents = { SelectionChanging: function (sender, info) { initSelection(info.newSelections[0], info.oldSelections[0]); } }; //设置选中行底色 //@param function setSelStyle(sel, backColor, sheet) { sel.row = sel.row === -1 ? 0 : sel.row; renderSheetFunc(sheet, function () { let style = projTreeObj.getSelStyle(backColor); for (let i = 0; i < sel.rowCount; i++) { let row = i + sel.row; sheet.setStyle(row, -1, style); } }); } //初始化焦点 //@param {Object}newSel {Object}oldSel @return {void} function initSelection(newSel, oldSel = null) { let node = tree.items[newSel.row]; tree.selected = node; shareSeleted = node; //恢复底色 if (oldSel) { setSelStyle(oldSel, projTreeObj.setting.style.defalutBackColor, spreadObj.sheet); } //设置选中行底色 if (newSel) { setSelStyle(newSel, projTreeObj.setting.style.selectedColor, spreadObj.sheet); } preSelection = newSel; } //渲染时方法,停止渲染 //@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 setSpreadOptions(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); //let spreadWidth = getWorkBookWidth(); for (let i = 0, len = headers.length; i < len; i++) { sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader); if (headers[i].formatter) { sheet.setFormatter(-1, i, headers[i].formatter); } sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader); 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]); } } //建表 //@return {void} function buildSheet() { spreadObj.workBook = new GC.Spread.Sheets.Workbook(spreadDom[0], { sheetCount: 1 }); sheetCommonObj.spreadDefaultStyle(spreadObj.workBook); spreadObj.sheet = spreadObj.workBook.getActiveSheet(); setSpreadOptions(spreadObj.workBook, spreadOpts); bindEvent(spreadObj.workBook, spreadEvents); buildHeader(spreadObj.sheet, headers); //全表不可编辑 spreadObj.sheet.getRange(-1, -1, -1, -1).locked(true); } //此项目的分享权限信息(可能会被父级项目覆盖,以新为准) //@param {String}userID(本用户id) {Object}project(项目) @return {Object} || {Null} function getShareInfo(userID, project) { if (!project.actualTreeInfo) { return null; } //获取跟本用户和选中项目相关的分享信息 let shareList = []; let actualID = project.actualTreeInfo.ID, actualData = actualIDShareInfo[actualID]; while (actualData) { for (let data of actualData.shareInfo) { if (data.userID === userID) { shareList.push(data); break; } } actualData = actualIDShareInfo[actualData.ParentID]; } //获取最新分享 shareList.sort(function (a, b) { return Date.parse(b.updateDate) - Date.parse(a.updateDate); }); return shareList[0] || null; } //此项目是否可以拷贝 //@param {String}userID {Object}project @return {Boolean} function isAllowCopy(userID, project) { let myShareInfo = getShareInfo(userID, project); if (!myShareInfo) { return false; } return !!myShareInfo.allowCopy; } //此项目是否可以协作 //@param {String}userID {Object}project @return {Boolean} function isAllowCoop(userID, project) { let myShareInfo = getShareInfo(userID, project); if (!myShareInfo) { return false; } return !!myShareInfo.allowCooperate; } //获取树节点 //@param {Object}tree @return {Object} function getTreeNodeCell(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 if (showTreeLine) { // Draw Horizontal Line if (centerX < x + w) { drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, 'gray'); 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, 'gray'); } else { drawLine(ctx, centerX, y, centerX, y1, 'gray'); } } } // 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, 'gray'); } } parent = parent.parent; parentCenterX -= (indent + levelIndent); } }; // Draw Text arguments[2] = x + (node.depth() + 1) * indent + node.depth() * levelIndent + imgWidth + 3; arguments[4] = 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]; if (node && node.data.projType === projectType.tender) { info.isReservedLocation = true; } return info; }; TreeNodeCellType.prototype.processMouseDown = function (hitinfo) { let offset = -1; let node = tree.items[hitinfo.row]; 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; 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 }); //(图标+名字)区域 function withingClickArea() { return hitinfo.x > centerX + halfBoxLength && hitinfo.x < centerX + halfBoxLength + imgWidth + indent / 2 + 3 + textLength; } //点击单位工程 if (node.data.projType === projectType.tender) { /*let newTab = window.open('about:blank'); //打开项目的实际ID BeforeOpenProject(node.data.actualTreeInfo.ID, {'fullFolder': GetFullFolder(node.parent)}, function () { let mainUrl = `/main?project=${node.data.actualTreeInfo.ID}`; CommonAjax.get(mainUrl, [], function () { newTab.location.href = mainUrl; }); });*/ let thisClick = Date.now(), open = false; if (this.preNode === node && this.preClick && thisClick - this.preClick <= 300) { open = true; projTreeObj.openTender(node.data.actualTreeInfo.ID, node.parent, 200); } this.preClick = open ? null : thisClick; this.preNode = open ? null : node; } 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.processMouseMove = function (hitInfo) { let sheet = hitInfo.sheet; let div = sheet.getParent().getHost(); let canvasId = div.id + "vp_vp"; let canvas = $(`#${canvasId}`)[0]; //改变鼠标图案 if (sheet && hitInfo.isReservedLocation) { canvas.style.cursor='pointer'; return true; }else{ canvas.style.cursor='default'; } return false; };*/ 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(); } //互动单元格 function getInteractionCell() { let editImg = document.getElementById('edit_pic'), editImgWidth = 13, editImgHeight = 13, copyImg = document.getElementById('copy_pic'), copyImgWidth = 13, copyImgHeight = 13; let InteractionCell = function () { }; InteractionCell.prototype = new GC.Spread.Sheets.CellTypes.Text(); InteractionCell.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 node = tree.items[options.row]; // Draw Text GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments); if (node && node.data.projType === projectType.tender) { let text = options.sheet.getText(options.row, options.col); let acStyle = options.sheet.getActualStyle(options.row, options.col), zoom = options.sheet.zoom(); let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, { sheet: options.sheet, row: options.row, col: options.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport }); const imgIndent = 5; let nowX = Math.floor(x) + textLength + imgIndent, nowY = Math.floor((y + (y + h)) / 2) - 7; if (node.data.allowCooperate) { ctx.drawImage(editImg, nowX, nowY, editImgWidth, editImgHeight); nowX += editImgWidth; } if (node.data.allowCopy) { ctx.drawImage(copyImg, nowX, nowY, copyImgWidth, copyImgHeight); } } }; InteractionCell.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 }; }; InteractionCell.prototype.processMouseDown = function (hitinfo) { let dataCode = headers[hitinfo.col]['dataCode']; let node = 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 === 'from') { if (node.data.shareType === shareType.receive) { $('#userinfo').find('h4').text(node.data.userInfo.name); $('#userinfo').find('h6').text(node.data.userInfo.company); let mobileHtml = ` ${node.data.userInfo.mobile ? node.data.userInfo.mobile : ''}`; $('#userinfo').find('li:first-child').html(mobileHtml); let emailHtml = ` ${node.data.userInfo.email ? node.data.userInfo.email : ''}`; $('#userinfo').find('li:last-child').html(emailHtml); $('#userinfo').modal('show'); } } } }; InteractionCell.prototype.processMouseMove = function (hitInfo) { let dataCode = headers[hitInfo.col]['dataCode']; let node = tree.items[hitInfo.row]; 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 InteractionCell(); } function isUnread(unreadList, node) { if (!unreadList) { return false; } const actualID = node && node.data && node.data.actualTreeInfo && node.data.actualTreeInfo.ID || null; if (!actualID) { return false; } return !!unreadList.find(ID => ID === actualID); } const foreColor = '#007bff'; const dangerColor = '#dc3545'; // 标记已读 // 打开任意的单位工程,都会将其父分享条目标记和自身为已读 // eg:被分享了一个建设项目,和其下一个单位工程,打开该一个单位工程,建设项目标记为已读、该单位工程也标记为已读 function handleMarkRead(unreadList, markReadProjectIDs) { const col = headers.findIndex(item => item.dataCode === 'shareDate'); const sheet = spreadObj.workBook.getActiveSheet(); const style = new GC.Spread.Sheets.Style(); projTreeObj.renderSheetFuc(sheet, function () { markReadProjectIDs.forEach(projectID => { SHARE_TO.removeUnread(projectID, unreadList); tree.items.forEach(node => { if (node.data && node.data.actualTreeInfo && node.data.actualTreeInfo.ID === projectID) { const row = node.serialNo(); sheet.setStyle(row, col, style); } }); }); }); } //显示树结构数据 //@param {Array}nodes {Array}headers @return {void} function showTreeData(nodes, headers) { let sheet = spreadObj.workBook.getActiveSheet(); let fuc = function () { sheet.setRowCount(nodes.length); for (let i = 0; i < nodes.length; i++) { let treeNodeCell = getTreeNodeCell(tree); sheet.getCell(i, treeCol).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']]); let dataCode = headers[j].dataCode; if (dataCode === 'from') { let style = new GC.Spread.Sheets.Style(); style.foreColor = foreColor; sheet.setStyle(i, j, style); sheet.getCell(i, j).cellType(getInteractionCell()); } else if (dataCode === 'shareDate') { let style = new GC.Spread.Sheets.Style(); if (isUnread(unreadShareList, nodes[i])) { style.foreColor = dangerColor; } sheet.setStyle(i, j, style); } sheet.setValue(i, j, nodes[i].data[dataCode] !== null && typeof nodes[i].data[dataCode] !== 'undefined' ? nodes[i].data[dataCode] : ''); } } }; renderSheetFunc(sheet, fuc); } // 获取实际树ID为某值的所有节点 function getNodesByActualID(ID, items) { return items.filter(node => node.data && node.data.actualTreeInfo && node.data.actualTreeInfo.ID === ID); } //同一棵树,可能存在相同数据显示多条的问题(传入的datas中不存在相同数据) //将真实树结构数据存在actualTreeInfo中,外部树结构数据用uuid重置。 //@param {Array}datas function setTreeInfo(datas) { let IDMapping = {}; for (let data of datas) { //项目真实ID与项目分享信息映射,方便确定项目的权限 if (!actualIDShareInfo[data.ID]) { actualIDShareInfo[data.ID] = { ID: data.ID, ParentID: data.ParentID, NextSiblingID: data.NextSiblingID, shareInfo: data.shareInfo }; } IDMapping[data.ID] = uuid.v1(); } for (let data of datas) { data.actualTreeInfo = { ID: data.ID, ParentID: data.ParentID, NextSiblingID: data.NextSiblingID }; data.ID = IDMapping[data.ID]; data.NextSiblingID = IDMapping[data.NextSiblingID] ? IDMapping[data.NextSiblingID] : -1; data.ParentID = IDMapping[data.ParentID] ? IDMapping[data.ParentID] : -1; } } //整理同层数据的NextSiblingID,ParentID //@param {Array}datas {Number || String}pid @return {void} function sortSameDepthData(datas, pid) { for (let i = 0; i < datas.length; i++) { let data = datas[i], nextData = datas[i + 1]; data.NextSiblingID = nextData ? nextData.ID : -1; data.ParentID = pid; } } //给项目设置分享信息:由xx分享、分享时间、分享给我,含有userInfo信息的文件为他人直接分享的文件,他人分享父级文件,子文件不含有userInfo信息 //@param {Array}datas @return {void} function setShareInfo(datas) { for (let data of datas) { if (data.userInfo) { //shareInfo中我的条目 let selfInfo = _.find(data.shareInfo, { userID: userID }); data.shareDate = selfInfo ? selfInfo.shareDate : '' data.from = data.userInfo.name; data.to = '分享给 我'; data.cancel = '清除'; } } } //给项目设置汇总信息 //@param {Array}projs {Object}summaryInfo function setSummaryInfo(grouped, summaryInfo) { if (!summaryInfo) { return; } let allDatas = []; for (let data of grouped) { allDatas.push(data); if (data.children && data.children.length > 0) { allDatas = allDatas.concat(data.children); } } for (let proj of allDatas) { let summaryProj = summaryInfo[proj.ID]; if (summaryProj) { proj.totalCost = summaryProj.totalCost; } } } //从同层树数据获取第一个节点ID //@param {Array}treeDatas树的数据 @return {String}第一个节点的虚拟树ID function getFirstID(treeDatas) { let treeMapping = {}; //建立ID索引 for (let data of treeDatas) { //新建一个简单对象,防止污染treeDatas的数据 treeMapping[data.ID] = { ID: data.ID, prev: null, next: null }; } //绑定prev next for (let data of treeDatas) { let me = treeMapping[data.ID], next = treeMapping[data.NextSiblingID]; if (next) { me.next = next; next.prev = me; } } //返回没有prev属性的数据 let result = _.find(treeDatas, function (data) { return !treeMapping[data.ID].prev }); return result ? result.ID : -1; } //获取可成树的数据 //@param {Array}datas @return {Array} function getTreeDatas(groupedDatas, ungroupedDatas) { //设置新的树结构数据 for (let data of groupedDatas) { setTreeInfo([data].concat(data.children)); } //未分类分段 let tenders = _.filter(ungroupedDatas, { projType: projectType.tender }); setTreeInfo(tenders); let rst = []; //整理树结构 sortSameDepthData(groupedDatas, -1); //第一个根节点数据 let firstID = getFirstID(groupedDatas); //新建未分类建设项目及单项工程 let ungroupedProj = { ID: uuid.v1(), ParentID: -1, NextSiblingID: firstID, name: '未分类建设项目', projType: projectType.project }; /*if (groupedDatas.length > 0) { groupedDatas[groupedDatas.length - 1].NextSiblingID = ungroupedProj.ID; }*/ //将未分类的数据归类 sortSameDepthData(tenders, ungroupedProj.ID); let allDatas = groupedDatas.concat(ungroupedDatas); //设置分享信息及操作信息 setShareInfo(allDatas); for (let data of allDatas) { rst.push(data); if (data.children) { rst = rst.concat(data.children); } } rst.push(ungroupedProj); return rst; } //按照时间排序 //@param {Array}datas @return {void} function sortByDate(datas) { datas.sort(function (a, b) { let shareInfoA = _.find(a.shareInfo, { userID }), shareInfoB = _.find(b.shareInfo, { userID }); let aV = shareInfoA ? Date.parse(shareInfoA.shareDate) : 0, bV = shareInfoB ? Date.parse(shareInfoB.shareDate) : 0; //时间越晚越靠前 if (aV > bV) { return -1; } else if (aV < bV) { return 1; } return 0; }); } //设置节点数据权限 //@param {Array}datas项目数据 function setPermissionsInfo(datas) { //data.allowCopy与shareInfo里allowCopy的区别: //data.allowCopy为该单位实际的权限(跟着最新的分享信息走,可能随着父项) for (let data of datas) { if (data.projType === projectType.tender) { data.allowCopy = isAllowCopy(userID, data); data.allowCooperate = isAllowCoop(userID, data); } } } //建立树 //@return void function initShareTree() { $.bootstrapLoading.start(); //获取分享数据 CommonAjax.post('/pm/api/receiveProjects', { user_id: userID }, function (rstData) { // 排序 --分享的文件按照时间先后顺序排序,分享文件下的子文件,按照原本树结构显示,不需要排序 sortByDate(rstData.grouped); sortByDate(rstData.ungrouped); //设置汇总信息 if (rstData.summaryInfo) { setSummaryInfo(rstData.grouped, rstData.summaryInfo.grouped); setSummaryInfo(rstData.ungrouped, rstData.summaryInfo.ungrouped); } let treeDatas = getTreeDatas(rstData.grouped, rstData.ungrouped); setPermissionsInfo(treeDatas); tree = pmTree.createNew(treeSetting, treeDatas); tree.selected = tree.items[0]; showTreeData(tree.items, headers); //初始选择 let initSel = spreadObj.sheet.getSelections()[0] ? spreadObj.sheet.getSelections()[0] : { row: 0, rowCount: 1 }; initSelection(initSel); autoFlashHeight(); spreadObj.sheet.frozenColumnCount(4); spreadObj.workBook.refresh(); $.bootstrapLoading.end(); }); } //初始化右键菜单 function initContextMenu() { $.contextMenu({ selector: '#shareSpread', build: function ($trigger, e) { let target = SheetDataHelper.safeRightClickSelection($trigger, e, spreadObj.workBook); initSelection({ row: target.row, rowCount: 1 }, preSelection ? preSelection : null, spreadObj.sheet); return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader; }, items: { "copy": { name: "拷贝工程", icon: 'fa-copy', disabled: function () { let selected = tree.selected; return !(selected && selected.data.allowCopy); }, callback: function (key, opt) { $('#copyShare').modal('show'); } }, "cancel": { name: "清除", icon: 'fa-remove', disabled: function () { let selected = tree.selected; return !(selected && selected.data.cancel && selected.data.cancel === '清除'); }, callback: function (key, opt) { let $p = $('
').text(`点“确定”按钮,确认清除分享文件 “${tree.selected.data.name}”。`); $('#cancelShare').find('.modal-body').empty(); $('#cancelShare').find('.modal-body').append($p); $('#cancelShare').modal('show'); } } } }); } //初始化视图 //@return void function initView() { if (tree) { tree = null; } if (spreadObj.workBook) { spreadObj.workBook.destroy(); spreadObj.workBook = null; } initContextMenu(); buildSheet(); initShareTree(); } //根据建设项目获取单项工程 //@param {Number}projID @return {void} function setEng(projID) { let engQuery = { $or: [{ deleteInfo: null }, { 'deleteInfo.deleted': false }], projType: projectType.engineering, userID: userID, ParentID: projID }; CommonAjax.post('/pm/api/getProjectsByQuery', { user_id: userID, query: engQuery, options: '-_id -property' }, function (rstData) { $('#copyShare_selectEng').empty(); for (let eng of rstData) { let opt = $('