pm_share.js 49 KB

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