pm_share.js 50 KB

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