pm_share.js 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Zhong
  6. * @date 2018/6/28
  7. * @version
  8. */
  9. const pmShare = (function () {
  10. const spreadDom = $('#shareSpread');
  11. let spreadObj = {workBook: null, sheet: null};
  12. let preSelection = null;
  13. //项目分享类型,由别人分享给自己的,和自己分享给别人的
  14. const shareType = {receive: 'receive', shareTo: 'shareTo'};
  15. //操作类型
  16. const oprType = {copy: 'copy', cancel: 'cancel'};
  17. let tree = null,
  18. actualIDShareInfo = {};//项目真实树ID与项目分享信息映射
  19. const treeCol = 0;
  20. const treeSetting = {
  21. tree: {
  22. id: 'ID',
  23. pid: 'ParentID',
  24. nid: 'NextSiblingID',
  25. rootId: -1,
  26. autoUpdate: false
  27. }
  28. };
  29. const headers = [
  30. {name: '工程列表', dataCode: 'name', width: 300, rateWidth: 0.55, vAlign: 'center', hAlign: 'left'},
  31. {name: '来自', dataCode: 'from', width: 80, rateWidth: 0.15, vAlign: 'center', hAlign: 'left'},
  32. {name: '分享时间', dataCode: 'shareDate', width: 140, rateWidth: 0.15, vAlign: 'center', hAlign: 'left'},
  33. {name: '总造价', dataCode: 'totalCost', width: 100, vAlign: 'center', hAlign: 'right', formatter: '0.00'},
  34. {name: '项目类别', dataCode: 'valuationType', width: 100, vAlign: 'center', hAlign: 'left'},
  35. ];
  36. const spreadOpts = {
  37. workBook: {
  38. tabStripVisible: false,
  39. allowContextMenu: false,
  40. allowCopyPasteExcelStyle : false,
  41. allowExtendPasteRange: false,
  42. allowUserDragDrop : false,
  43. allowUserDragFill: false,
  44. scrollbarMaxAlign : true
  45. },
  46. sheet: {
  47. isProtected: true,
  48. protectionOptions: {allowResizeRows: true, allowResizeColumns: true},
  49. clipBoardOptions: GC.Spread.Sheets.ClipboardPasteOptions.values
  50. }
  51. };
  52. const spreadEvents = {
  53. SelectionChanging: function (sender, info) {
  54. initSelection(info.newSelections[0], info.oldSelections[0]);
  55. }
  56. };
  57. //设置选中行底色
  58. //@param
  59. function setSelStyle(sel, backColor,sheet) {
  60. sel.row = sel.row === -1 ? 0 : sel.row;
  61. renderSheetFunc(sheet, function () {
  62. let style = projTreeObj.getSelStyle(backColor);
  63. for(let i = 0; i < sel.rowCount; i++){
  64. let row = i + sel.row;
  65. sheet.setStyle(row, -1, style);
  66. }
  67. });
  68. }
  69. //初始化焦点
  70. //@param {Object}newSel {Object}oldSel @return {void}
  71. function initSelection(newSel, oldSel = null) {
  72. let node = tree.items[newSel.row];
  73. tree.selected = node;
  74. shareSeleted = node;
  75. //恢复底色
  76. if(oldSel){
  77. setSelStyle(oldSel, projTreeObj.setting.style.defalutBackColor, spreadObj.sheet);
  78. }
  79. //设置选中行底色
  80. if(newSel){
  81. setSelStyle(newSel, projTreeObj.setting.style.selectedColor, spreadObj.sheet);
  82. }
  83. preSelection = newSel;
  84. }
  85. //渲染时方法,停止渲染
  86. //@param {Object}sheet {Function}func @return {void}
  87. function renderSheetFunc(sheet, func){
  88. sheet.suspendEvent();
  89. sheet.suspendPaint();
  90. if(func){
  91. func();
  92. }
  93. sheet.resumeEvent();
  94. sheet.resumePaint();
  95. }
  96. //设置表选项
  97. //@param {Object}workBook {Object}opts @return {void}
  98. function setSpreadOptions (workBook, opts) {
  99. for(let opt in opts.workBook){
  100. workBook.options[opt] = opts.workBook[opt];
  101. }
  102. for(let opt in opts.sheet){
  103. workBook.getActiveSheet().options[opt] = opts.sheet[opt];
  104. }
  105. }
  106. //建表头
  107. //@param {Object}sheet {Array}headers @return {void}
  108. function buildHeader(sheet, headers) {
  109. let fuc = function () {
  110. sheet.setColumnCount(headers.length);
  111. sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
  112. //let spreadWidth = getWorkBookWidth();
  113. for(let i = 0, len = headers.length; i < len; i++){
  114. sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
  115. if(headers[i].formatter){
  116. sheet.setFormatter(-1, i, headers[i].formatter);
  117. }
  118. sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
  119. sheet.getRange(-1, i, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[i]['hAlign']]);
  120. sheet.getRange(-1, i, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[i]['vAlign']]);
  121. }
  122. };
  123. renderSheetFunc(sheet, fuc);
  124. }
  125. //表监听事件
  126. //@param {Object}workBook @return {void}
  127. function bindEvent(workBook, events) {
  128. if(Object.keys(events).length === 0){
  129. return;
  130. }
  131. const Events = GC.Spread.Sheets.Events;
  132. for(let event in events){
  133. workBook.bind(Events[event], events[event]);
  134. }
  135. }
  136. //建表
  137. //@return {void}
  138. function buildSheet(){
  139. spreadObj.workBook = new GC.Spread.Sheets.Workbook(spreadDom[0], {sheetCount: 1});
  140. sheetCommonObj.spreadDefaultStyle(spreadObj.workBook);
  141. spreadObj.sheet = spreadObj.workBook.getActiveSheet();
  142. setSpreadOptions(spreadObj.workBook, spreadOpts);
  143. bindEvent(spreadObj.workBook, spreadEvents);
  144. buildHeader(spreadObj.sheet, headers);
  145. //全表不可编辑
  146. spreadObj.sheet.getRange(-1, -1, -1, -1).locked(true);
  147. }
  148. //此项目的分享权限信息(可能会被父级项目覆盖,以新为准)
  149. //@param {String}userID(本用户id) {Object}project(项目) @return {Object} || {Null}
  150. function getShareInfo(userID, project) {
  151. if (!project.actualTreeInfo) {
  152. return null;
  153. }
  154. //获取跟本用户和选中项目相关的分享信息
  155. let shareList = [];
  156. let actualID = project.actualTreeInfo.ID,
  157. actualData = actualIDShareInfo[actualID];
  158. while (actualData) {
  159. for (let data of actualData.shareInfo) {
  160. if (data.userID === userID) {
  161. shareList.push(data);
  162. break;
  163. }
  164. }
  165. actualData = actualIDShareInfo[actualData.ParentID];
  166. }
  167. //获取最新分享
  168. shareList.sort(function (a, b) {
  169. let aV = Date.parse(a.shareDate),
  170. bV = Date.parse(b.shareDate);
  171. if (aV > bV) {
  172. return -1;
  173. } else if (aV < bV) {
  174. return 1;
  175. }
  176. return 0;
  177. });
  178. return shareList[0] || null;
  179. }
  180. //此项目是否可以拷贝
  181. //@param {String}userID {Object}project @return {Boolean}
  182. function isAllowCopy(userID, project){
  183. let myShareInfo = getShareInfo(userID, project);
  184. if (!myShareInfo) {
  185. return false;
  186. }
  187. return !!myShareInfo.allowCopy;
  188. }
  189. //此项目是否可以协作
  190. //@param {String}userID {Object}project @return {Boolean}
  191. function isAllowCoop(userID, project) {
  192. let myShareInfo = getShareInfo(userID, project);
  193. if (!myShareInfo) {
  194. return false;
  195. }
  196. return !!myShareInfo.allowCooperate;
  197. }
  198. //获取树节点
  199. //@param {Object}tree @return {Object}
  200. function getTreeNodeCell(tree){
  201. let indent = 20;
  202. let levelIndent = -5;
  203. let halfBoxLength = 5;
  204. let halfExpandLength = 3;
  205. let imgWidth = 18;
  206. let imgHeight = 14;
  207. let TreeNodeCellType = function () {
  208. };
  209. TreeNodeCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
  210. TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
  211. if (style.backColor) {
  212. ctx.save();
  213. ctx.fillStyle = style.backColor;
  214. ctx.fillRect(x, y, w, h);
  215. ctx.restore();
  216. } else {
  217. ctx.clearRect(x, y, w, h);
  218. }
  219. let drawLine = function (canvas, x1, y1, x2, y2, color) {
  220. ctx.save();
  221. ctx.translate(0.5, 0.5);
  222. ctx.beginPath();
  223. ctx.moveTo(x1, y1);
  224. ctx.lineTo(x2, y2);
  225. ctx.strokeStyle = color;
  226. ctx.stroke();
  227. ctx.restore();
  228. };
  229. let drawExpandBox = function (ctx, x, y, w, h, centerX, centerY, expanded) {
  230. let rect = {}, h1, h2, offset = 1;
  231. rect.top = centerY - halfBoxLength;
  232. rect.bottom = centerY + halfBoxLength;
  233. rect.left = centerX - halfBoxLength;
  234. rect.right = centerX + halfBoxLength;
  235. if (rect.left < x + w) {
  236. rect.right = Math.min(rect.right, x + w);
  237. ctx.save();
  238. ctx.translate(0.5, 0.5);
  239. ctx.strokeStyle = 'black';
  240. ctx.beginPath();
  241. ctx.moveTo(rect.left, rect.top);
  242. ctx.lineTo(rect.left, rect.bottom);
  243. ctx.lineTo(rect.right, rect.bottom);
  244. ctx.lineTo(rect.right, rect.top);
  245. ctx.lineTo(rect.left, rect.top);
  246. ctx.stroke();
  247. ctx.fillStyle = 'white';
  248. ctx.fill();
  249. ctx.restore();
  250. // Draw Horizontal Line
  251. h1 = centerX - halfExpandLength;
  252. h2 = Math.min(centerX + halfExpandLength, x + w);
  253. if (h2 > h1) {
  254. drawLine(ctx, h1, centerY, h2, centerY, 'black');
  255. }
  256. // Draw Vertical Line
  257. if (!expanded && (centerX < x + w)) {
  258. drawLine(ctx, centerX, centerY - halfExpandLength, centerX, centerY + halfExpandLength, 'black');
  259. }
  260. }
  261. }
  262. let node = tree.items[options.row];
  263. let showTreeLine = true;
  264. if (!node) { return; }
  265. let centerX = Math.floor(x) + node.depth() * indent + node.depth() * levelIndent + indent / 2;
  266. let x1 = centerX + indent / 2;
  267. let centerY = Math.floor((y + (y + h)) / 2);
  268. let y1;
  269. // Draw Sibling Line
  270. if (showTreeLine) {
  271. // Draw Horizontal Line
  272. if (centerX < x + w) {
  273. drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, 'gray');
  274. let img;
  275. if(node.data.projType === projectType.folder){
  276. img = document.getElementById('folder_open_pic');
  277. imgWidth = 15;
  278. }
  279. else if(node.data.projType === projectType.project){
  280. img = document.getElementById('proj_pic');
  281. imgWidth = 18;
  282. }
  283. else if(node.data.projType === projectType.engineering){
  284. img = document.getElementById('eng_pic');
  285. imgWidth = 14;
  286. }
  287. else if(node.data.projType === projectType.tender){
  288. img = document.getElementById('tender_pic');
  289. imgWidth = 14;
  290. }
  291. ctx.drawImage(img, centerX+indent/2+3, centerY - 7, imgWidth,imgHeight);
  292. }
  293. // Draw Vertical Line
  294. if (centerX < x + w) {
  295. y1 = node.isLast() ? centerY : y + h;
  296. if (node.isFirst() && !node.parent.parent) {
  297. drawLine(ctx, centerX, centerY, centerX, y1, 'gray');
  298. } else {
  299. drawLine(ctx, centerX, y, centerX, y1, 'gray');
  300. }
  301. }
  302. }
  303. // Draw Expand Box
  304. if (node.children.length > 0) {
  305. drawExpandBox(ctx, x, y, w, h, centerX, centerY, node.expanded);
  306. }
  307. // Draw Parent Line
  308. if (showTreeLine) {
  309. var parent = node.parent, parentCenterX = centerX - indent - levelIndent;
  310. while (parent.parent) {
  311. if (!parent.isLast()) {
  312. if (parentCenterX < x + w) {
  313. drawLine(ctx, parentCenterX, y, parentCenterX, y + h, 'gray');
  314. }
  315. }
  316. parent = parent.parent;
  317. parentCenterX -= (indent + levelIndent);
  318. }
  319. };
  320. // Draw Text
  321. arguments[2] = x + (node.depth() + 1) * indent + node.depth() * levelIndent + imgWidth + 3;
  322. arguments[4] = w - (node.depth() + 1) * indent - node.depth() * levelIndent - imgWidth - 3;
  323. GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
  324. };
  325. TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
  326. let info = {x: x, y: y, row: context.row, col: context.col, cellStyle: cellStyle, cellRect: cellRect, sheetArea: context.sheetArea};
  327. let node = tree.items[info.row];
  328. let offset = -1;
  329. let centerX = info.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
  330. let text = context.sheet.getText(info.row, info.col);
  331. let value = context.sheet.getValue(info.row, info.col);
  332. let acStyle = context.sheet.getActualStyle(info.row, info.col),
  333. zoom = context.sheet.zoom();
  334. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: context.sheet, row: info.row, col: info.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  335. if(info.x > centerX + halfBoxLength && info.x < centerX + halfBoxLength + imgWidth + indent/2+3 + textLength){
  336. info.isReservedLocation = true;
  337. }
  338. return info;
  339. };
  340. TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
  341. let offset = -1;
  342. let node = tree.items[hitinfo.row];
  343. let centerX = hitinfo.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
  344. let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;
  345. let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
  346. let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
  347. let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
  348. zoom = hitinfo.sheet.zoom();
  349. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  350. //(图标+名字)区域
  351. function withingClickArea(){
  352. return hitinfo.x > centerX + halfBoxLength && hitinfo.x < centerX + halfBoxLength + imgWidth + indent/2+3 + textLength;
  353. }
  354. //点击单位工程
  355. if(node.data.projType === projectType.tender && withingClickArea()){
  356. let newTab = window.open('about:blank');
  357. //打开项目的实际ID
  358. BeforeOpenProject(node.data.actualTreeInfo.ID, {'fullFolder': GetFullFolder(node.parent)}, function () {
  359. let mainUrl = `/main?project=${node.data.actualTreeInfo.ID}`;
  360. CommonAjax.get(mainUrl, [], function () {
  361. newTab.location.href = mainUrl;
  362. });
  363. });
  364. }
  365. if (!node || node.children.length === 0) { return; }
  366. if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 &&
  367. hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) {
  368. node.setExpanded(!node.expanded);
  369. TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
  370. let iCount = node.posterityCount(), i, child;
  371. for (i = 0; i < iCount; i++) {
  372. child = tree.items[hitinfo.row + i + 1];
  373. hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.visible, hitinfo.sheetArea);
  374. }
  375. hitinfo.sheet.invalidateLayout();
  376. });
  377. hitinfo.sheet.repaint();
  378. }
  379. };
  380. TreeNodeCellType.prototype.processMouseMove = function (hitInfo) {
  381. let sheet = hitInfo.sheet;
  382. let div = sheet.getParent().getHost();
  383. let canvasId = div.id + "vp_vp";
  384. let canvas = $(`#${canvasId}`)[0];
  385. //改变鼠标图案
  386. if (sheet && hitInfo.isReservedLocation) {
  387. canvas.style.cursor='pointer';
  388. return true;
  389. }else{
  390. canvas.style.cursor='default';
  391. }
  392. return false;
  393. };
  394. TreeNodeCellType.prototype.processMouseEnter = function (hitinfo) {
  395. let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
  396. let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
  397. let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
  398. let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
  399. zoom = hitinfo.sheet.zoom();
  400. let node = tree.items[hitinfo.row];
  401. let nodeIndent = node ? (node.depth() + 1) * indent + node.depth() * levelIndent + imgWidth + 3 : 0;
  402. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  403. let cellWidth = hitinfo.sheet.getCell(-1, hitinfo.col).width();
  404. if(textLength > cellWidth - nodeIndent){
  405. TREE_SHEET_HELPER.showTipsDiv(text,{pos: {}},hitinfo);
  406. }
  407. };
  408. TreeNodeCellType.prototype.processMouseLeave = function (hitinfo) {
  409. TREE_SHEET_HELPER.tipDiv = 'hide';
  410. if (TREE_SHEET_HELPER._toolTipElement) {
  411. $(TREE_SHEET_HELPER._toolTipElement).hide();
  412. TREE_SHEET_HELPER._toolTipElement = null;
  413. };
  414. TREE_SHEET_HELPER.tipDivCheck();//延时检查:当tips正在show的时候,就调用了hide方法,会导致tips一直存在,所以设置一个超时处理
  415. }
  416. return new TreeNodeCellType();
  417. }
  418. //互动单元格
  419. function getInteractionCell() {
  420. let workImg = document.getElementById('work_pic'),
  421. workImgWidth = 13,
  422. workImgHeight = 13,
  423. copyImg = document.getElementById('copy_pic'),
  424. copyImgWidth = 13,
  425. copyImgHeight = 13;
  426. let InteractionCell = function () {
  427. };
  428. InteractionCell.prototype = new GC.Spread.Sheets.CellTypes.Text();
  429. InteractionCell.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
  430. if (style.backColor) {
  431. ctx.save();
  432. ctx.fillStyle = style.backColor;
  433. ctx.fillRect(x, y, w, h);
  434. ctx.restore();
  435. } else {
  436. ctx.clearRect(x, y, w, h);
  437. }
  438. let node = tree.items[options.row];
  439. // Draw Text
  440. GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
  441. if (node && node.data.projType === projectType.tender) {
  442. let text = options.sheet.getText(options.row, options.col);
  443. let acStyle = options.sheet.getActualStyle(options.row, options.col),
  444. zoom = options.sheet.zoom();
  445. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: options.sheet, row: options.row, col: options.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  446. let nowX = Math.floor(x) + textLength + 3,
  447. nowY = Math.floor((y + (y + h)) / 2) - 7;
  448. if (node.data.allowCooperate) {
  449. ctx.drawImage(workImg, nowX, nowY, workImgWidth, workImgHeight);
  450. nowX += workImgWidth;
  451. }
  452. if (node.data.allowCopy) {
  453. ctx.drawImage(copyImg, nowX, nowY, copyImgWidth, copyImgHeight);
  454. }
  455. }
  456. };
  457. InteractionCell.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
  458. return {
  459. x: x,
  460. y: y,
  461. row: context.row,
  462. col: context.col,
  463. cellStyle: cellStyle,
  464. cellRect: cellRect,
  465. sheetArea: context.sheetArea,
  466. isReservedLocation: true
  467. };
  468. };
  469. InteractionCell.prototype.processMouseDown = function (hitinfo) {
  470. let dataCode = headers[hitinfo.col]['dataCode'];
  471. let node = tree.items[hitinfo.row];
  472. let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
  473. let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
  474. let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
  475. zoom = hitinfo.sheet.zoom();
  476. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  477. if(hitinfo.x - hitinfo.cellRect.x > 0 && hitinfo.x - hitinfo.cellRect.x < textLength){
  478. //由..分享,弹出分享者信息
  479. if(dataCode === 'from'){
  480. if(node.data.shareType === shareType.receive){
  481. $('#userinfo').find('h4').text(node.data.userInfo.name);
  482. $('#userinfo').find('h6').text(node.data.userInfo.company);
  483. let mobileHtml = `<i class="fa fa-tablet"> ${node.data.userInfo.mobile ? node.data.userInfo.mobile : ''}</i>`;
  484. $('#userinfo').find('li:first-child').html(mobileHtml);
  485. let emailHtml = `<i class="fa fa-envelope-o"> ${node.data.userInfo.email ? node.data.userInfo.email : ''}</i>`;
  486. $('#userinfo').find('li:last-child').html(emailHtml);
  487. $('#userinfo').modal('show');
  488. }
  489. }
  490. }
  491. };
  492. InteractionCell.prototype.processMouseMove = function (hitInfo) {
  493. let dataCode = headers[hitInfo.col]['dataCode'];
  494. let node = tree.items[hitInfo.row];
  495. let sheet = hitInfo.sheet;
  496. let div = sheet.getParent().getHost();
  497. let canvasId = div.id + "vp_vp";
  498. let canvas = $(`#${canvasId}`)[0];
  499. //改变鼠标图案
  500. let text = hitInfo.sheet.getText(hitInfo.row, hitInfo.col);
  501. let value = hitInfo.sheet.getValue(hitInfo.row, hitInfo.col);
  502. let acStyle = hitInfo.sheet.getActualStyle(hitInfo.row, hitInfo.col),
  503. zoom = hitInfo.sheet.zoom();
  504. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitInfo.sheet, row: hitInfo.row, col: hitInfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  505. if (sheet && hitInfo.x - hitInfo.cellRect.x > 0 && hitInfo.x - hitInfo.cellRect.x < textLength) {
  506. canvas.style.cursor='pointer';
  507. return true;
  508. }else{
  509. canvas.style.cursor='default';
  510. }
  511. return false;
  512. };
  513. return new InteractionCell();
  514. }
  515. //设置分享给界面数据
  516. //@param {Object}selected @return {void}
  517. function setShareToModal(selected){
  518. $('#shareToInfo').empty();
  519. if(!selected){
  520. return;
  521. }
  522. let userIDs = [];
  523. for(let user of selected.data.shareInfo){
  524. userIDs.push(user.userID);
  525. }
  526. CommonAjax.post('/user/getUsers', {userIDs: userIDs}, function (rstData) {
  527. for(let userInfo of rstData){
  528. for(let user of selected.data.shareInfo){
  529. if(user.userID === userInfo._id){
  530. user.name = userInfo.real_name;
  531. user.company = userInfo.company;
  532. user.mobile = userInfo.mobile;
  533. user.email = userInfo.email;
  534. }
  535. }
  536. }
  537. let infoArr = [];
  538. for(let user of selected.data.shareInfo){
  539. let infoHtml = `<tr>
  540. <td style="width: 106px;">${user.name}</td>
  541. <td style="width: 146px;">${user.company}</td>
  542. <td style="width: 146px;">${user.mobile}</td>
  543. <td style="width: 156px;">${user.email}</td>
  544. <td style="width: 70px;text-align: center"><input value="allowCopy" ${user.allowCopy ? 'checked' : ''} type="checkbox"></td>
  545. <td style="width: 70px;text-align: center"><input value="cancelShare" type="checkbox"></td>
  546. </tr>`;
  547. infoArr.push(infoHtml);
  548. }
  549. let infoHtml = infoArr.join('');
  550. $('#shareToInfo').html(infoHtml);
  551. });
  552. }
  553. //更新项目分享信息
  554. //@param {Object}selected
  555. function updateShareInfo(selected){
  556. if(!selected){
  557. return;
  558. }
  559. let usersTr = $('#shareToInfo').find('tr');
  560. let newShareInfo = [];
  561. for(let i = 0; i < usersTr.length; i++){
  562. let userTr = usersTr[i];
  563. let allowCopy = $(userTr).find('input:first').prop('checked');
  564. let cancelShare = $(userTr).find('input:last').prop('checked');
  565. selected.data.shareInfo[i].allowCopy = allowCopy;
  566. if(!cancelShare){
  567. newShareInfo.push(selected.data.shareInfo[i]);
  568. }
  569. }
  570. CommonAjax.post('/pm/api/updateProjects', {user_id: userID, updateData: [{updateType: 'update', updateData: {ID: selected.data.ID, shareInfo: newShareInfo}}]}, function () {
  571. selected.data.shareInfo = newShareInfo;
  572. if(newShareInfo.length === 0){
  573. renderSheetFunc(spreadObj.sheet, function () {
  574. let rIdx = selected.serialNo();
  575. tree.removeNode(selected);
  576. spreadObj.sheet.deleteRows(rIdx, 1);
  577. spreadObj.sheet.setRowCount(tree.items);
  578. initSelection({row: spreadObj.sheet.getActiveRowIndex(), rowCount: 1},null);
  579. });
  580. }
  581. });
  582. }
  583. const foreColor = '#007bff';
  584. const cancelForeColor = 'red';
  585. //显示树结构数据
  586. //@param {Array}nodes {Array}headers @return {void}
  587. function showTreeData(nodes, headers){
  588. let sheet = spreadObj.workBook.getActiveSheet();
  589. let fuc = function(){
  590. sheet.setRowCount(nodes.length);
  591. for(let i = 0; i < nodes.length; i++){
  592. let treeNodeCell = getTreeNodeCell(tree);
  593. sheet.getCell(i, treeCol).cellType(treeNodeCell);
  594. for(let j = 0; j < headers.length; j++){
  595. sheet.getRange(-1, j, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[j]['hAlign']]);
  596. sheet.getRange(-1, j, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[j]['vAlign']]);
  597. let dataCode = headers[j].dataCode;
  598. if(dataCode === 'from'){
  599. let style = new GC.Spread.Sheets.Style();
  600. style.foreColor = foreColor;
  601. sheet.setStyle(i, j, style);
  602. sheet.getCell(i, j).cellType(getInteractionCell());
  603. }
  604. sheet.setValue(i, j, nodes[i].data[dataCode] !== null && typeof nodes[i].data[dataCode] !== 'undefined' ? nodes[i].data[dataCode] : '');
  605. }
  606. }
  607. };
  608. renderSheetFunc(sheet, fuc);
  609. }
  610. //同一棵树,可能存在相同数据显示多条的问题(传入的datas中不存在相同数据)
  611. //将真实树结构数据存在actualTreeInfo中,外部树结构数据用uuid重置。
  612. //@param {Array}datas
  613. function setTreeInfo(datas) {
  614. let IDMapping = {};
  615. for (let data of datas) {
  616. //项目真实ID与项目分享信息映射,方便确定项目的权限
  617. if (!actualIDShareInfo[data.ID]) {
  618. actualIDShareInfo[data.ID] = {ID: data.ID, ParentID: data.ParentID, NextSiblingID: data.NextSiblingID, shareInfo: data.shareInfo};
  619. }
  620. IDMapping[data.ID] = uuid.v1();
  621. }
  622. for (let data of datas) {
  623. data.actualTreeInfo = {ID: data.ID, ParentID: data.ParentID, NextSiblingID: data.NextSiblingID};
  624. data.ID = IDMapping[data.ID];
  625. data.NextSiblingID = IDMapping[data.NextSiblingID] ? IDMapping[data.NextSiblingID] : -1;
  626. data.ParentID = IDMapping[data.ParentID] ? IDMapping[data.ParentID] : -1;
  627. }
  628. }
  629. //整理同层数据的NextSiblingID,ParentID
  630. //@param {Array}datas {Number || String}pid @return {void}
  631. function sortSameDepthData(datas, pid) {
  632. for (let i = 0; i < datas.length; i++) {
  633. let data = datas[i],
  634. nextData = datas[i + 1];
  635. data.NextSiblingID = nextData ? nextData.ID : -1;
  636. data.ParentID = pid;
  637. }
  638. }
  639. //给项目设置分享信息:由xx分享、分享时间、分享给我,含有userInfo信息的文件为他人直接分享的文件,他人分享父级文件,子文件不含有userInfo信息
  640. //@param {Array}datas @return {void}
  641. function setShareInfo(datas) {
  642. for (let data of datas) {
  643. if (data.userInfo) {
  644. //shareInfo中我的条目
  645. let selfInfo = _.find(data.shareInfo, {userID: userID});
  646. data.shareDate = selfInfo ? selfInfo.shareDate : ''
  647. data.from = data.userInfo.name;
  648. data.to = '分享给 我';
  649. data.cancel = '清除';
  650. }
  651. }
  652. }
  653. //给项目设置汇总信息
  654. //@param {Array}projs {Object}summaryInfo
  655. function setSummaryInfo(grouped, summaryInfo) {
  656. if (!summaryInfo) {
  657. return;
  658. }
  659. let allDatas = [];
  660. for (let data of grouped) {
  661. allDatas.push(data);
  662. if (data.children && data.children.length > 0) {
  663. allDatas = allDatas.concat(data.children);
  664. }
  665. }
  666. for(let proj of allDatas){
  667. let summaryProj = summaryInfo[proj.ID];
  668. if(summaryProj){
  669. proj.totalCost = summaryProj.totalCost;
  670. }
  671. }
  672. }
  673. //从同层树数据获取第一个节点ID
  674. //@param {Array}treeDatas树的数据 @return {String}第一个节点的虚拟树ID
  675. function getFirstID(treeDatas) {
  676. let treeMapping = {};
  677. //建立ID索引
  678. for (let data of treeDatas) {
  679. //新建一个简单对象,防止污染treeDatas的数据
  680. treeMapping[data.ID] = {ID: data.ID, prev: null, next: null};
  681. }
  682. //绑定prev next
  683. for (let data of treeDatas) {
  684. let me = treeMapping[data.ID],
  685. next = treeMapping[data.NextSiblingID];
  686. if (next) {
  687. me.next = next;
  688. next.prev = me;
  689. }
  690. }
  691. //返回没有prev属性的数据
  692. let result = _.find(treeDatas, function (data) {
  693. return !treeMapping[data.ID].prev
  694. });
  695. return result ? result.ID : -1;
  696. }
  697. //获取可成树的数据
  698. //@param {Array}datas @return {Array}
  699. function getTreeDatas(groupedDatas, ungroupedDatas){
  700. //设置新的树结构数据
  701. for (let data of groupedDatas) {
  702. setTreeInfo([data].concat(data.children));
  703. }
  704. //未分类分段
  705. let tenders = _.filter(ungroupedDatas, {projType: projectType.tender});
  706. setTreeInfo(tenders);
  707. let rst = [];
  708. //整理树结构
  709. sortSameDepthData(groupedDatas, -1);
  710. //第一个根节点数据
  711. let firstID = getFirstID(groupedDatas);
  712. //新建未分类建设项目及单项工程
  713. let ungroupedProj = {ID: uuid.v1(), ParentID: -1, NextSiblingID: firstID, name: '未分类建设项目', projType: projectType.project};
  714. /*if (groupedDatas.length > 0) {
  715. groupedDatas[groupedDatas.length - 1].NextSiblingID = ungroupedProj.ID;
  716. }*/
  717. //将未分类的数据归类
  718. sortSameDepthData(tenders, ungroupedProj.ID);
  719. let allDatas = groupedDatas.concat(ungroupedDatas);
  720. //设置分享信息及操作信息
  721. setShareInfo(allDatas);
  722. for (let data of allDatas) {
  723. rst.push(data);
  724. if (data.children) {
  725. rst = rst.concat(data.children);
  726. }
  727. }
  728. rst.push(ungroupedProj);
  729. return rst;
  730. }
  731. //按照时间排序
  732. //@param {Array}datas @return {void}
  733. function sortByDate(datas){
  734. datas.sort(function (a, b) {
  735. let shareInfoA = _.find(a.shareInfo, {userID}),
  736. shareInfoB = _.find(b.shareInfo, {userID});
  737. let aV = shareInfoA ? Date.parse(shareInfoA.shareDate) : 0,
  738. bV = shareInfoB ? Date.parse(shareInfoB.shareDate) : 0;
  739. //时间越晚越靠前
  740. if (aV > bV) {
  741. return -1;
  742. } else if (aV < bV) {
  743. return 1;
  744. }
  745. return 0;
  746. });
  747. }
  748. //设置节点数据权限
  749. //@param {Array}datas项目数据
  750. function setPermissionsInfo(datas) {
  751. //data.allowCopy与shareInfo里allowCopy的区别:
  752. //data.allowCopy为该单位实际的权限(跟着最新的分享信息走,可能随着父项)
  753. for (let data of datas) {
  754. if (data.projType === projectType.tender) {
  755. data.allowCopy = isAllowCopy(userID, data);
  756. data.allowCooperate = isAllowCoop(userID, data);
  757. }
  758. }
  759. }
  760. //建立树
  761. //@return void
  762. function initShareTree(){
  763. $.bootstrapLoading.start();
  764. //获取分享数据
  765. CommonAjax.post('/pm/api/receiveProjects', {user_id: userID}, function (rstData) {
  766. // 排序 --分享的文件按照时间先后顺序排序,分享文件下的子文件,按照原本树结构显示,不需要排序
  767. sortByDate(rstData.grouped);
  768. sortByDate(rstData.ungrouped);
  769. //设置汇总信息
  770. if (rstData.summaryInfo) {
  771. setSummaryInfo(rstData.grouped, rstData.summaryInfo.grouped);
  772. setSummaryInfo(rstData.ungrouped, rstData.summaryInfo.ungrouped);
  773. }
  774. let treeDatas = getTreeDatas(rstData.grouped, rstData.ungrouped);
  775. setPermissionsInfo(treeDatas);
  776. tree = pmTree.createNew(treeSetting, treeDatas);
  777. tree.selected = tree.items[0];
  778. showTreeData(tree.items, headers);
  779. //初始选择
  780. let initSel = spreadObj.sheet.getSelections()[0] ? spreadObj.sheet.getSelections()[0] : {row: 0, rowCount: 1};
  781. initSelection(initSel);
  782. autoFlashHeight();
  783. spreadObj.sheet.frozenColumnCount(4);
  784. spreadObj.workBook.refresh();
  785. $.bootstrapLoading.end();
  786. });
  787. }
  788. //初始化右键菜单
  789. function initContextMenu() {
  790. $.contextMenu({
  791. selector: '#shareSpread',
  792. build: function ($trigger, e) {
  793. let target = SheetDataHelper.safeRightClickSelection($trigger, e, spreadObj.workBook);
  794. initSelection({row: target.row, rowCount: 1}, preSelection ? preSelection : null, spreadObj.sheet);
  795. return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
  796. },
  797. items: {
  798. "copy": {
  799. name: "拷贝工程",
  800. icon: 'fa-copy',
  801. disabled: function () {
  802. let selected = tree.selected;
  803. return !(selected && selected.data.allowCopy);
  804. },
  805. callback: function (key, opt) {
  806. $('#copyShare').modal('show');
  807. }
  808. },
  809. "cancel": {
  810. name: "清除",
  811. icon: 'fa-remove',
  812. disabled: function () {
  813. let selected = tree.selected;
  814. return !(selected && selected.data.cancel && selected.data.cancel === '清除');
  815. },
  816. callback: function (key, opt) {
  817. let $p = $('<p>').text(`点“确定”按钮,确认清除分享文件 “${tree.selected.data.name}”。`);
  818. $('#cancelShare').find('.modal-body').empty();
  819. $('#cancelShare').find('.modal-body').append($p);
  820. $('#cancelShare').modal('show');
  821. }
  822. }
  823. }
  824. });
  825. }
  826. //初始化视图
  827. //@return void
  828. function initView(){
  829. if(tree){
  830. tree = null;
  831. }
  832. if(spreadObj.workBook){
  833. spreadObj.workBook.destroy();
  834. spreadObj.workBook = null;
  835. }
  836. initContextMenu();
  837. buildSheet();
  838. initShareTree();
  839. }
  840. //根据建设项目获取单项工程
  841. //@param {Number}projID @return {void}
  842. function setEng(projID){
  843. let engQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], projType: projectType.engineering, userID: userID, ParentID: projID};
  844. CommonAjax.post('/pm/api/getProjectsByQuery', {user_id: userID, query: engQuery, options: '-_id -property'}, function (rstData) {
  845. $('#copyShare_selectEng').empty();
  846. for(let eng of rstData){
  847. let opt = $('<option>').val(eng.ID).text(eng.name);
  848. $('#copyShare_selectEng').append(opt);
  849. }
  850. });
  851. }
  852. //从其他建设项目中复制中,建设项目的文件层次结构名称和顺序
  853. //@param {Array}treeData @return {Array}
  854. function getFileHierarchyInfo(treeData){
  855. let tree = idTree.createNew({id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1});
  856. tree.loadDatas(treeData);
  857. let items = tree.items;
  858. let rst = [];
  859. function getFileHierarchyName(node){
  860. let nodeName = node.data.name;
  861. let name = [];
  862. while (node.parent){
  863. name.push(node.parent.data.name ? node.parent.data.name : '');
  864. node = node.parent;
  865. }
  866. name = name.reverse();
  867. name.push(nodeName);
  868. return name.join('\\');
  869. }
  870. for(let node of items){
  871. if(node.children.length === 0 ){//project
  872. rst.push({ID: node.data.ID, fileHierarchyName: getFileHierarchyName(node)})
  873. }
  874. }
  875. return rst;
  876. }
  877. //设置拷贝工程下拉选择
  878. //@return {void}
  879. function setCopyModal(){
  880. //获取建设项目
  881. let projQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], projType: {$in: [projectType.project, projectType.folder]}, userID: userID};
  882. CommonAjax.post('/pm/api/getProjectsByQuery', {user_id: userID, query: projQuery, options: '-_id -property'}, function (rstData) {
  883. let fileHierarchyData = getFileHierarchyInfo(rstData);
  884. $('#copyShare_selectProj').empty();
  885. for(let proj of fileHierarchyData){
  886. let opt = $('<option>').val(proj.ID).text(proj.fileHierarchyName);
  887. $('#copyShare_selectProj').append(opt);
  888. }
  889. //初始选择
  890. /*if(fileHierarchyData.length > 0){
  891. setEng(fileHierarchyData[0].ID);
  892. }*/
  893. });
  894. }
  895. //拷贝分享的工程
  896. //@param {Object}selected {Number}parentID @return {void}
  897. function copyShareProject(selected, projID){
  898. if(!projID || !selected){
  899. return;
  900. }
  901. let copyMap = {copy: null, update: null};
  902. let newName = getCopyName(selected);
  903. //获取建设项目的分段
  904. let tenderQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], userID: userID, ParentID: projID};
  905. CommonAjax.post('/pm/api/getProjectsByQuery', {user_id: userID, query: tenderQuery, options: '-_id -property'}, function (rstData) {
  906. let updateTender = null;
  907. for(let tender of rstData){
  908. if(tender.name === newName){
  909. $('#copyShare_name').text('已存在此单位工程。');
  910. $('#copyShare_name').addClass('text-danger');
  911. return;
  912. }
  913. if(tender.NextSiblingID == -1){
  914. updateTender = tender;
  915. }
  916. }
  917. //更新前节点
  918. if(updateTender){
  919. copyMap.update = {query: {ID: updateTender.ID}};
  920. }
  921. //拷贝
  922. let copyData = {
  923. userID: userID,
  924. ID: selected.data.actualTreeInfo.ID,
  925. NextSiblingID: -1,
  926. ParentID: projID,
  927. name: newName,
  928. shareInfo: [],
  929. compilation: selected.data.compilation,
  930. createDateTime: selected.data.createDateTime,
  931. fileVer: selected.data.fileVer ? selected.data.fileVer : '',
  932. projType: selected.data.projType,
  933. property: {},
  934. recentDateTime: selected.data.recentDateTime,
  935. fullFolder: selected.data.fullFolder
  936. };
  937. copyData.property.rootProjectID = projID;
  938. copyMap.copy = {document: copyData};
  939. $('#copyShare').modal('hide');
  940. $.bootstrapLoading.start();
  941. CommonAjax.post('/pm/api/copyProjects', {projectMap: copyMap, user_id: userID}, function (rstData) {
  942. $.bootstrapLoading.end();
  943. }, function () {
  944. $.bootstrapLoading.end();
  945. });
  946. });
  947. }
  948. //获取拷贝后的名称
  949. //@param {Object}node @return {String}
  950. function getCopyName(node) {
  951. //当前单位工程可能没有分享的用户信息,可能他人分享的是父级文件,userInfo在父级文件中
  952. let orgName = node.data.name,
  953. userInfo = node.data.userInfo;
  954. while (node && !userInfo) {
  955. node = node.parent;
  956. userInfo = node.data.userInfo;
  957. }
  958. return `${orgName} (${userInfo.name}分享拷贝)`;
  959. }
  960. //事件监听器
  961. //@return void
  962. function eventListener(){
  963. //tab
  964. $('#tab_pm_share').on('shown.bs.tab', function () {
  965. //侧滑隐藏
  966. $('.slide-sidebar').removeClass('open');
  967. $('.slide-sidebar').css('width', '0');
  968. projTreeObj.tree = null;
  969. if(projTreeObj.workBook){
  970. projTreeObj.workBook.destroy();
  971. projTreeObj.workBook = null;
  972. }
  973. gcTreeObj.tree = null;
  974. if(gcTreeObj.workBook){
  975. gcTreeObj.workBook.destroy();
  976. gcTreeObj.workBook = null;
  977. }
  978. initView();
  979. });
  980. //关闭拷贝工程
  981. $('#copyShare').on('hidden.bs.modal', function () {
  982. $('#copyShareProj-info').hide();
  983. $('#copyShareEng-info').hide();
  984. });
  985. //打开拷贝工程
  986. $('#copyShare').on('shown.bs.modal', function () {
  987. setCopyModal();
  988. //更改显示名称
  989. let newName = getCopyName(shareSeleted);
  990. $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
  991. $('#copyShare_name').removeClass('text-danger');
  992. });
  993. //拷贝工程改变选择建设项目
  994. $('#copyShare_selectProj').change(function () {
  995. //更改显示名称
  996. let newName = getCopyName(shareSeleted);
  997. $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
  998. $('#copyShare_name').removeClass('text-danger');
  999. $('#copyShareProj-info').hide();
  1000. $('#copyShareEng-info').hide();
  1001. let curSelID = $(this).select().val();
  1002. setEng(parseInt(curSelID));
  1003. });
  1004. //拷贝工程改变选择单项工程
  1005. $('#copyShare_selectEng').change(function () {
  1006. //更改显示名称
  1007. let newName = getCopyName(shareSeleted);
  1008. $('#copyShare_name').html(`拷贝后,工程将重命名为 "<b>${newName}</b>"`);
  1009. $('#copyShare_name').removeClass('text-danger');
  1010. });
  1011. //确认拷贝
  1012. $('#copyShare_confirm').click(function () {
  1013. let selProj = $('#copyShare_selectProj').select().val();
  1014. if(!selProj){
  1015. $('#copyShareProj-info').show();
  1016. return;
  1017. }
  1018. copyShareProject(tree.selected, parseInt(selProj));
  1019. });
  1020. //清除分享
  1021. //清除了该节点后,可能还有该节点的数据在树上(树允许有重复数据),需要更新分享信息
  1022. function updateAfterCancel(userID, projectID) {
  1023. for (let item of tree.items) {
  1024. if (item.data.actualTreeInfo && item.data.actualTreeInfo.ID === projectID) {
  1025. _.remove(item.data.shareInfo, function (data) {
  1026. return data.userID === userID;
  1027. });
  1028. }
  1029. }
  1030. }
  1031. $('#cancelShareConfirm').click(function () {
  1032. $.bootstrapLoading.start();
  1033. let cancelProjID = tree.selected.data.actualTreeInfo.ID;
  1034. CommonAjax.post('/pm/api/share', {user_id: userID, type: oprType.cancel, projectID: cancelProjID, shareData:[{userID: userID}]}, function (rstData) {
  1035. tree.removeNode(tree.selected);
  1036. //更新与清除节点数据相同,且为被清除缓存分享信息
  1037. updateAfterCancel(userID, cancelProjID);
  1038. //重新设置actualIDShareInfo,以正确更新权限(清除了分享信息后,可能会导致权限变化 eg:清除了新的分享,则存留的分享项目采用旧的)
  1039. actualIDShareInfo = {};
  1040. let treeDatas = [];
  1041. for (let item of tree.items) {
  1042. treeDatas.push(item.data);
  1043. let actualTreeInfo = item.data.actualTreeInfo;
  1044. if (actualTreeInfo && !actualIDShareInfo[actualTreeInfo.ID]) {
  1045. actualIDShareInfo[actualTreeInfo.ID] = {
  1046. ID: actualTreeInfo.ID,
  1047. ParentID: actualTreeInfo.ParentID,
  1048. NextSiblingID: actualTreeInfo.NextSiblingID,
  1049. shareInfo: item.data.shareInfo
  1050. };
  1051. }
  1052. }
  1053. //重新设置权限
  1054. setPermissionsInfo(treeDatas);
  1055. showTreeData(tree.items, headers);
  1056. $.bootstrapLoading.end();
  1057. }, function () {
  1058. $.bootstrapLoading.end();
  1059. });
  1060. });
  1061. }
  1062. return {spreadObj, headers, initView, eventListener}
  1063. })();
  1064. $(document).ready(function () {
  1065. pmShare.eventListener();
  1066. });