pm_gc.js 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282
  1. /**
  2. * Created by Zhong on 2017/10/30.
  3. */
  4. let gcTree = null;
  5. let decDate = null;//恢复后的名称后缀(时间+恢复)
  6. //恢复路径t = tender, e = engineering, p = project
  7. const recPath = {t: 'T', t_e: 'T_E', t_e_p: 'T_E_P', e: 'E', e_p: 'E_P', p: 'P'};
  8. const gcTreeObj = {
  9. tree: null,
  10. workBook: null,
  11. setting: {
  12. tree: {
  13. id: 'ID',
  14. pid: 'ParentID',
  15. nid: 'NextSiblingID',
  16. rootId: -1,
  17. autoUpdate: false
  18. },
  19. header: [
  20. {name: '工程列表', dataCode: 'name', width: 800, vAlign: 'center', hAlign: 'left'},
  21. {name: '删除日期', dataCode: 'deleteDateTime', width: 170, vAlign: 'center', hAlign: 'left'},
  22. {name: '创建日期', dataCode: 'createDateTime', width: 170, vAlign: 'center', hAlign: 'left'},
  23. {name: '恢复', dataCode: 'recovery', width: 100, vAlign: 'center', hAlign: 'left'},
  24. {name: '彻底删除', dataCode: 'delete', width: 100, vAlign: 'center', hAlign: 'left'},
  25. {name: '单价文件', dataCode: 'unitPriceFile', width: 100, vAlign: 'center', hAlign: 'left'},
  26. {name: '单价文件-清除', dataCode: 'unitPriceFile_delete', width: 100, vAlign: 'center', hAlign: 'left'},
  27. {name: '费率文件', dataCode: 'feeRateFile', width: 100, vAlign: 'center', hAlign: 'left'},
  28. {name: '费率文件-清除', dataCode: 'feeRateFile_delete', width: 100, vAlign: 'center', hAlign: 'left'}
  29. ],
  30. //恢复和彻底删除字体色
  31. style: {
  32. recForeColor: '#007bff',
  33. delForeColor: '#dc3545'
  34. },
  35. options: {
  36. tabStripVisible: false,
  37. allowCopyPasteExcelStyle : false,
  38. allowExtendPasteRange: false,
  39. allowUserDragDrop : false,
  40. allowUserDragFill: false,
  41. scrollbarMaxAlign : true
  42. }
  43. },
  44. renderSheetFuc: function (sheet, fuc) {
  45. sheet.suspendPaint();
  46. sheet.suspendEvent();
  47. fuc();
  48. sheet.resumePaint();
  49. sheet.resumeEvent();
  50. },
  51. setOptions: function (workbook, opts) {
  52. for(let opt in opts){
  53. workbook.options[opt] = opts[opt];
  54. }
  55. },
  56. bindEvent: function (workBook) {
  57. const _events = GC.Spread.Sheets.Events;
  58. let sheet = workBook.getActiveSheet();
  59. //改变选中节点set selected
  60. sheet.bind(_events.SelectionChanging, this.onSelectionChanging);
  61. },
  62. buildHeader: function (sheet, headers) {
  63. let me = this;
  64. let fuc = function () {
  65. sheet.options.isProtected = true;
  66. sheet.options.protectionOptions = {
  67. allowResizeRows: true,
  68. allowResizeColumns: true
  69. };
  70. sheet.setColumnCount(headers.length);
  71. sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
  72. for(let i = 0, len = headers.length; i < len; i++){
  73. sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
  74. if(headers[i].dataCode === 'unitPriceFile' || headers[i].dataCode === 'feeRateFile'){
  75. //合并列
  76. sheet.addSpan(0, i, 1, 2, GC.Spread.Sheets.SheetArea.colHeader);
  77. }
  78. if(headers[i].dataCode === 'unitPriceFile_delete' || headers[i].dataCode === 'feeRateFile_delete'){
  79. continue;
  80. }
  81. sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
  82. }
  83. };
  84. me.renderSheetFuc(sheet, fuc);
  85. },
  86. buildSheet: function () {
  87. if(!this.workBook){
  88. this.workBook = new GC.Spread.Sheets.Workbook($('#gcSpread')[0], {sheetCount: 1});
  89. this.setOptions(this.workBook, this.setting.options);
  90. this.buildHeader(this.workBook.getActiveSheet(), this.setting.header);
  91. this.bindEvent(this.workBook);
  92. }
  93. },
  94. getSelStyle: function (backColor) {
  95. let style = new GC.Spread.Sheets.Style();
  96. style.backColor = backColor;
  97. style.borderLeft = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
  98. style.borderTop = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
  99. style.borderRight = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
  100. style.borderBottom = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
  101. return style;
  102. },
  103. //设置选中行底色
  104. setSelStyle: function (sel, backColor) {
  105. let me = this;
  106. let sheet = me.workBook.getSheet(0);
  107. me.renderSheetFuc(sheet, function () {
  108. let style = me.getSelStyle(backColor);
  109. /*sel.row = sel.row === -1 ? 0 : sel.row;*/
  110. for(let i = 0; i < sel.rowCount; i++){
  111. let row = i + sel.row;
  112. sheet.setStyle(row, -1, style);
  113. }
  114. });
  115. },
  116. initSelection: function (newSel, oldSel = null) {
  117. let me = this;
  118. let node = me.tree.items[newSel.row];
  119. me.tree.selected = node;
  120. //恢复底色
  121. if(oldSel){
  122. me.setSelStyle(oldSel, projTreeObj.setting.style.defalutBackColor);
  123. }
  124. //设置选中行底色
  125. if(newSel){
  126. me.setSelStyle(newSel, projTreeObj.setting.style.selectedColor);
  127. }
  128. $(".tools-btn > a").not(".disabled").addClass("disabled");
  129. $("#add-engineering-btn").addClass("disabled");
  130. $('#add-tender-btn').removeClass('disabled');
  131. if(node){
  132. switch(node.data.projType) {
  133. case projectType.project:
  134. $("#del-btn").removeClass("disabled");
  135. $("#add-engineering-btn").removeClass("disabled");
  136. break;
  137. case projectType.folder:
  138. if(!node.children || node.children.length === 0){
  139. $("#del-btn").removeClass("disabled");
  140. }
  141. break;
  142. case projectType.engineering:
  143. $("#del-btn").removeClass("disabled");
  144. $("#add-engineering-btn").removeClass("disabled");
  145. break;
  146. case projectType.tender:
  147. $("#add-engineering-btn").removeClass("disabled");
  148. $("#move-to-btn").removeClass("disabled");
  149. $("#copy-to-btn").removeClass("disabled");
  150. $("#share-btn").removeClass("disabled");
  151. $("#cooperate-btn").removeClass("disabled");
  152. $("#del-btn").removeClass("disabled");
  153. break;
  154. }
  155. $("#rename-btn").removeClass("disabled");
  156. }
  157. },
  158. onSelectionChanging: function (sender, args) {
  159. let me = gcTreeObj;
  160. me.initSelection(args.newSelections[0], args.oldSelections[0]);
  161. },
  162. //点击恢复列,弹出恢复项目窗口
  163. oprProj: function (modalId, node) {
  164. let tenderNodes = m_getTenders(node);
  165. let type = modalId === '#rePoj' ? 'recovery' : 'delete';
  166. $(`${modalId} .modal-header`).empty();
  167. $('p', `${modalId} .modal-body`).remove();
  168. $(`${modalId} .modal-header`).html(v_getTitle(type, node));
  169. $(`${modalId} .modal-body`).html(v_getMoBody(type, node, tenderNodes));
  170. $(`${modalId}`).modal('show');
  171. },
  172. //点击单价文件恢复,弹出恢复单价文件窗口
  173. recoveryUnitPrc: function (node) {
  174. let unitPriceFiles = node.data.unitPriceFiles;
  175. let tenders = m_getTenders(node);
  176. $('#reFile h5').text('恢复单价文件');
  177. $('tr', '#reFile tbody').remove();
  178. $('#reFile tbody').html(v_getFiles(fileType.unitPriceFile, unitPriceFiles, tenders, 'recovery'));
  179. $('#reFile').modal('show');
  180. },
  181. recoveryFeeRate: function (node) {
  182. let feeRateFiles = node.data.feeRateFiles;
  183. let tenders = m_getTenders(node);
  184. $('#reFile h5').text('恢复费率文件');
  185. $('tr', '#reFile tbody').remove();
  186. $('#reFile tbody').html(v_getFiles(fileType.feeRateFile, feeRateFiles, tenders, 'recovery'));
  187. $('#reFile').modal('show');
  188. },
  189. //点击单价文件清除,弹出清除单价文件窗口
  190. deleteUnitPrc: function (node) {
  191. let unitPriceFiles = node.data.unitPriceFiles;
  192. let tenders = m_getTenders(node);
  193. $('#delFile h5').text('彻底删除单价文件');
  194. $('tr', '#delFile tbody').remove();
  195. $('#delFile tbody').html(v_getFiles(fileType.unitPriceFile, unitPriceFiles, tenders, 'delete'));
  196. $('#delFile').modal('show');
  197. },
  198. deleteFeeRate: function (node) {
  199. let feeRateFiles = node.data.feeRateFiles;
  200. let tenders = m_getTenders(node);
  201. $('#delFile h5').text('彻底删除费率文件');
  202. $('tr', '#delFile tbody').remove();
  203. $('#delFile tbody').html(v_getFiles(fileType.feeRateFile, feeRateFiles, tenders, 'delete'));
  204. $('#delFile').modal('show');
  205. },
  206. getTreeNodeCell: function (tree) {
  207. let indent = 20;
  208. let levelIndent = -5;
  209. let halfBoxLength = 5;
  210. let halfExpandLength = 3;
  211. let imgWidth = 18;
  212. let imgHeight = 14;
  213. let TreeNodeCellType = function () {
  214. };
  215. TreeNodeCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
  216. TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
  217. if (style.backColor) {
  218. ctx.save();
  219. ctx.fillStyle = style.backColor;
  220. ctx.fillRect(x, y, w, h);
  221. ctx.restore();
  222. } else {
  223. ctx.clearRect(x, y, w, h);
  224. }
  225. let drawLine = function (canvas, x1, y1, x2, y2, color) {
  226. ctx.save();
  227. ctx.translate(0.5, 0.5);
  228. ctx.beginPath();
  229. ctx.moveTo(x1, y1);
  230. ctx.lineTo(x2, y2);
  231. ctx.strokeStyle = color;
  232. ctx.stroke();
  233. ctx.restore();
  234. };
  235. let drawExpandBox = function (ctx, x, y, w, h, centerX, centerY, expanded) {
  236. let rect = {}, h1, h2, offset = 1;
  237. rect.top = centerY - halfBoxLength;
  238. rect.bottom = centerY + halfBoxLength;
  239. rect.left = centerX - halfBoxLength;
  240. rect.right = centerX + halfBoxLength;
  241. if (rect.left < x + w) {
  242. rect.right = Math.min(rect.right, x + w);
  243. ctx.save();
  244. ctx.translate(0.5, 0.5);
  245. ctx.strokeStyle = 'black';
  246. ctx.beginPath();
  247. ctx.moveTo(rect.left, rect.top);
  248. ctx.lineTo(rect.left, rect.bottom);
  249. ctx.lineTo(rect.right, rect.bottom);
  250. ctx.lineTo(rect.right, rect.top);
  251. ctx.lineTo(rect.left, rect.top);
  252. ctx.stroke();
  253. ctx.fillStyle = 'white';
  254. ctx.fill();
  255. ctx.restore();
  256. // Draw Horizontal Line
  257. h1 = centerX - halfExpandLength;
  258. h2 = Math.min(centerX + halfExpandLength, x + w);
  259. if (h2 > h1) {
  260. drawLine(ctx, h1, centerY, h2, centerY, 'black');
  261. }
  262. // Draw Vertical Line
  263. if (!expanded && (centerX < x + w)) {
  264. drawLine(ctx, centerX, centerY - halfExpandLength, centerX, centerY + halfExpandLength, 'black');
  265. }
  266. }
  267. }
  268. let node = tree.items[options.row];
  269. let showTreeLine = true;
  270. if (!node) { return; }
  271. let centerX = Math.floor(x) + node.depth() * indent + node.depth() * levelIndent + indent / 2;
  272. let x1 = centerX + indent / 2;
  273. let centerY = Math.floor((y + (y + h)) / 2);
  274. let y1;
  275. // Draw Sibling Line
  276. if (showTreeLine) {
  277. // Draw Horizontal Line
  278. if (centerX < x + w) {
  279. drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, 'gray');
  280. let img;
  281. if(node.data.projType === projectType.folder){
  282. img = document.getElementById('folder_open_pic');
  283. imgWidth = 15;
  284. }
  285. else if(node.data.projType === projectType.project){
  286. img = document.getElementById('proj_pic');
  287. imgWidth = 18;
  288. }
  289. else if(node.data.projType === projectType.engineering){
  290. img = document.getElementById('eng_pic');
  291. imgWidth = 14;
  292. }
  293. else if(node.data.projType === projectType.tender){
  294. img = document.getElementById('tender_pic');
  295. imgWidth = 14;
  296. }
  297. ctx.drawImage(img, centerX+indent/2+3, centerY - 7, imgWidth,imgHeight);
  298. }
  299. // Draw Vertical Line
  300. if (centerX < x + w) {
  301. y1 = node.isLast() ? centerY : y + h;
  302. if (node.isFirst() && !node.parent.parent) {
  303. drawLine(ctx, centerX, centerY, centerX, y1, 'gray');
  304. } else {
  305. drawLine(ctx, centerX, y, centerX, y1, 'gray');
  306. }
  307. }
  308. }
  309. // Draw Expand Box
  310. if (node.children.length > 0) {
  311. drawExpandBox(ctx, x, y, w, h, centerX, centerY, node.expanded);
  312. }
  313. // Draw Parent Line
  314. if (showTreeLine) {
  315. var parent = node.parent, parentCenterX = centerX - indent - levelIndent;
  316. while (parent.parent) {
  317. if (!parent.isLast()) {
  318. if (parentCenterX < x + w) {
  319. drawLine(ctx, parentCenterX, y, parentCenterX, y + h, 'gray');
  320. }
  321. }
  322. parent = parent.parent;
  323. parentCenterX -= (indent + levelIndent);
  324. }
  325. };
  326. // Draw Text
  327. //x = x + (node.depth() + 1) * indent + node.depth() * levelIndent;
  328. x = x + (node.depth() + 1) * indent + node.depth() * levelIndent + imgWidth + 3;
  329. GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
  330. };
  331. TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
  332. let info = {x: x, y: y, row: context.row, col: context.col, cellStyle: cellStyle, cellRect: cellRect, sheetArea: context.sheetArea};
  333. let node = tree.items[info.row];
  334. let offset = -1;
  335. let centerX = info.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
  336. let text = context.sheet.getText(info.row, info.col);
  337. let value = context.sheet.getValue(info.row, info.col);
  338. let acStyle = context.sheet.getActualStyle(info.row, info.col),
  339. zoom = context.sheet.zoom();
  340. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: context.sheet, row: info.row, col: info.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  341. if(info.x > centerX + halfBoxLength && info.x < centerX + halfBoxLength + imgWidth + indent/2+3 + textLength){
  342. info.isReservedLocation = true;
  343. }
  344. return info;
  345. };
  346. TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
  347. let offset = -1;
  348. let node = tree.items[hitinfo.row];
  349. tree.selected = node;
  350. let centerX = hitinfo.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
  351. let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;;
  352. if (!node || node.children.length === 0) { return; }
  353. if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
  354. node.setExpanded(!node.expanded);
  355. TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
  356. let iCount = node.posterityCount(), i, child;
  357. for (i = 0; i < iCount; i++) {
  358. child = tree.items[hitinfo.row + i + 1];
  359. hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.visible, hitinfo.sheetArea);
  360. }
  361. hitinfo.sheet.invalidateLayout();
  362. });
  363. hitinfo.sheet.repaint();
  364. }
  365. };
  366. return new TreeNodeCellType();
  367. },
  368. getBaseCell: function () {
  369. let MyBaseCell = function () {
  370. };
  371. MyBaseCell.prototype = new GC.Spread.Sheets.CellTypes.Text();
  372. MyBaseCell.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
  373. return {
  374. x: x,
  375. y: y,
  376. row: context.row,
  377. col: context.col,
  378. cellStyle: cellStyle,
  379. cellRect: cellRect,
  380. sheetArea: context.sheetArea,
  381. isReservedLocation: true
  382. };
  383. };
  384. MyBaseCell.prototype.processMouseDown = function (hitinfo) {
  385. let dataCode = gcTreeObj.setting.header[hitinfo.col]['dataCode'];
  386. let node = gcTreeObj.tree.items[hitinfo.row];
  387. let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
  388. let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
  389. let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
  390. zoom = hitinfo.sheet.zoom();
  391. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  392. if(hitinfo.x - hitinfo.cellRect.x > 0 && hitinfo.x - hitinfo.cellRect.x < textLength){
  393. //恢复
  394. if(dataCode === 'recovery'){
  395. gcTreeObj.oprProj('#rePoj', node);
  396. }
  397. //清除
  398. else if(dataCode === 'delete'){
  399. gcTreeObj.oprProj('#delPoj', node)
  400. }
  401. //恢复单价文件
  402. else if(dataCode === 'unitPriceFile'){
  403. gcTreeObj.recoveryUnitPrc(node);
  404. }
  405. //清除单价文件
  406. else if(dataCode === 'unitPriceFile_delete'){
  407. gcTreeObj.deleteUnitPrc(node);
  408. }
  409. //恢复费率文件
  410. else if(dataCode === 'feeRateFile'){
  411. gcTreeObj.recoveryFeeRate(node);
  412. }
  413. //清除费率文件
  414. else if(dataCode === 'feeRateFile_delete'){
  415. gcTreeObj.deleteFeeRate(node);
  416. }
  417. }
  418. };
  419. MyBaseCell.prototype.processMouseMove = function (hitInfo) {
  420. let dataCode = gcTreeObj.setting.header[hitInfo.col]['dataCode'];
  421. if(dataCode === 'recovery' || dataCode === 'delete' || dataCode === 'unitPriceFile' || dataCode === 'unitPriceFile_delete' || dataCode === 'feeRateFile' || dataCode === 'feeRateFile_delete'){
  422. let sheet = hitInfo.sheet;
  423. let div = sheet.getParent().getHost();
  424. let canvasId = div.id + "vp_vp";
  425. let canvas = $(`#${canvasId}`)[0];
  426. //改变鼠标图案
  427. let text = hitInfo.sheet.getText(hitInfo.row, hitInfo.col);
  428. let value = hitInfo.sheet.getValue(hitInfo.row, hitInfo.col);
  429. let acStyle = hitInfo.sheet.getActualStyle(hitInfo.row, hitInfo.col),
  430. zoom = hitInfo.sheet.zoom();
  431. let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitInfo.sheet, row: hitInfo.row, col: hitInfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
  432. if (sheet && hitInfo.x - hitInfo.cellRect.x > 0 && hitInfo.x - hitInfo.cellRect.x < textLength) {
  433. canvas.style.cursor='pointer';
  434. return true;
  435. }else{
  436. canvas.style.cursor='default';
  437. }
  438. }
  439. return false;
  440. };
  441. return new MyBaseCell();
  442. },
  443. setCellValue: function (cell, node) {
  444. const sheet = this.workBook.getActiveSheet();
  445. const {row, col} = cell;
  446. const dataCode = this.setting.header[col]['dataCode'];
  447. let value = '';
  448. if(dataCode === 'deleteDateTime' || dataCode === 'createDateTime'){
  449. if (node.data.projType === projectType.tender && deleted(node)) {
  450. let date = dataCode === 'deleteDateTime' ? node.data.deleteInfo.deleteDateTime : node.data.createDateTime;
  451. let localDateTime = new Date(date).toLocaleDateString();
  452. value = new Date(localDateTime).Format('yyyy-MM-dd');
  453. }
  454. }
  455. else if(dataCode === 'recovery'){
  456. if(deleted(node)){
  457. value = '恢复';
  458. }
  459. }
  460. else if(dataCode === 'delete'){
  461. if(deleted(node)){
  462. value = '彻底删除';
  463. }
  464. }
  465. else if(dataCode === 'unitPriceFile'){
  466. if(node.data.projType === projectType.project && node.data.unitPriceFiles !== undefined && node.data.unitPriceFiles.length > 0){
  467. value = '恢复';
  468. }
  469. }
  470. else if(dataCode === 'unitPriceFile_delete'){
  471. if(node.data.projType === projectType.project && node.data.unitPriceFiles !== undefined && node.data.unitPriceFiles.length > 0){
  472. value = '彻底删除';
  473. }
  474. }
  475. else if(dataCode === 'feeRateFile'){
  476. if(node.data.projType === projectType.project && node.data.feeRateFiles !== undefined && node.data.feeRateFiles.length > 0){
  477. value = '恢复';
  478. }
  479. }
  480. else if(dataCode === 'feeRateFile_delete'){
  481. if(node.data.projType === projectType.project && node.data.feeRateFiles !== undefined && node.data.feeRateFiles.length > 0){
  482. value = '彻底删除';
  483. }
  484. }
  485. else {
  486. value = node.data[dataCode] ? node.data[dataCode] : '';
  487. }
  488. sheet.setValue(row, col, value);
  489. },
  490. showTreeData: function (nodes, headers) {
  491. let me = this;
  492. let sheet = me.workBook.getActiveSheet();
  493. let fuc = function(){
  494. sheet.setRowCount(nodes.length);
  495. for(let i = 0; i < nodes.length; i++){
  496. let treeNodeCell = me.getTreeNodeCell(me.tree);
  497. sheet.getCell(i, 0).cellType(treeNodeCell);
  498. for(let j = 0; j < headers.length; j++){
  499. sheet.getRange(-1, j, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[j]['hAlign']]);
  500. sheet.getRange(-1, j, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[j]['vAlign']]);
  501. if(j !== 0){
  502. sheet.getCell(i, j).cellType(me.getBaseCell());
  503. }
  504. let dataCode = headers[j].dataCode;
  505. if(dataCode === 'recovery' || dataCode === 'unitPriceFile' || dataCode === 'feeRateFile'){
  506. let style = new GC.Spread.Sheets.Style();
  507. style.foreColor = me.setting.style.recForeColor;
  508. sheet.setStyle(-1, j, style);
  509. }
  510. else if(dataCode === 'delete' || dataCode === 'unitPriceFile_delete' || dataCode === 'feeRateFile_delete'){
  511. let style = new GC.Spread.Sheets.Style();
  512. style.foreColor = me.setting.style.delForeColor;
  513. sheet.setStyle(-1, j, style);
  514. }
  515. me.setCellValue({row: i, col: j}, nodes[i]);
  516. }
  517. }
  518. };
  519. me.renderSheetFuc(sheet, fuc);
  520. },
  521. refreshNodeData: function (node) {
  522. let me = this;
  523. let sheet = me.workBook.getActiveSheet();
  524. let header = me.setting.header;
  525. let rIdx = me.tree.items.indexOf(node);
  526. me.renderSheetFuc(sheet, function () {
  527. for(let i = 0; i < header.length; i++){
  528. me.setCellValue({row: rIdx, col: i}, node);
  529. }
  530. });
  531. },
  532. remove: function (node) {
  533. let me = this;
  534. let sheet = me.workBook.getActiveSheet();
  535. //删除行号
  536. let rIdx = me.tree.items.indexOf(node);
  537. //删除行数
  538. let count = node.posterityCount() + 1;
  539. me.tree.removeNode(node);
  540. me.renderSheetFuc(sheet, function () {
  541. sheet.deleteRows(rIdx, count);
  542. sheet.setRowCount(me.tree.items.length);
  543. me.initSelection({row: sheet.getActiveRowIndex(), rowCount: 1});
  544. });
  545. },
  546. move: function (orgRow, newRow) {
  547. this.workBook.getActiveSheet().deleteRows(orgRow, 1);
  548. this.addRow(this.tree.items[newRow]);
  549. }
  550. };
  551. $(document).ready(function () {
  552. $('#tab_pm_gc').on('show.bs.tab', function () {
  553. //侧滑隐藏
  554. $('.slide-sidebar').removeClass('open');
  555. $('.slide-sidebar').css('width', '0');
  556. gc_init();
  557. if(projTreeObj.workBook){
  558. projTreeObj.workBook.destroy();
  559. projTreeObj.workBook = null;
  560. }
  561. projTreeObj.tree = null;
  562. });
  563. e_recFiles($('#reFileBtn'));
  564. e_delFiles($('#delFileBtn'));
  565. e_recProj($('#rePojBtn'));
  566. e_delProj($('#delPojBtn'));
  567. });
  568. function gc_init(){
  569. $.bootstrapLoading.start();
  570. a_getGC(function (datas) {
  571. m_buildVirtualTree(datas);
  572. let normalDatas = m_VTreeToDatas(datas);
  573. gcTreeObj.tree = pmTree.createNew(gcTreeObj.setting, normalDatas);
  574. gcTreeObj.tree.selected = gcTreeObj.tree.items[0];
  575. gcTreeObj.buildSheet();
  576. gcTreeObj.showTreeData(gcTreeObj.tree.items, gcTreeObj.setting.header);
  577. //初始选择
  578. let initSel = gcTreeObj.workBook.getSheet(0).getSelections()[0] ? gcTreeObj.workBook.getSheet(0).getSelections()[0] : {row: 0, rowCount: 1};
  579. gcTreeObj.initSelection(initSel);
  580. autoFlashHeight();
  581. gcTreeObj.workBook.refresh();
  582. $.bootstrapLoading.end();
  583. });
  584. }
  585. //项目恢复模态框标题
  586. function v_getTitle(type, node){
  587. let html = '';
  588. html += type === 'recovery' ? '<h5 class="modal-title">恢复 ' : '<h5 class="modal-title">彻底删除 ';
  589. if(node.data.projType === projectType.project){
  590. html += '<i class="fa fa-cubes"></i>建设项目</h5>';
  591. }
  592. else if(node.data.projType === projectType.engineering){
  593. html += '<i class="fa fa-cube"></i>单项工程</h5>';
  594. }
  595. else if(node.data.projType === projectType.tender){
  596. html += '<i class="fa fa-sticky-note-o"></i>单位工程</h5>';
  597. }
  598. html += '<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>';
  599. return html;
  600. }
  601. //项目恢复模态框主体
  602. function v_getMoBody(type, oprNode, nodes){
  603. let html = '';
  604. if(type === 'recovery'){
  605. if(oprNode.data.projType === projectType.tender){
  606. decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
  607. let recName = oprNode.data.name + decDate;
  608. html += '<p>恢复后将重命名为 <b>' + recName + '</b></p>';
  609. }
  610. else {
  611. if(oprNode.data.projType === projectType.project){
  612. html += '<p><i class="fa fa-cubes"></i> ' + oprNode.data.name + '下的单位工程都将恢复都将恢复,恢复后将重命名为</p>';
  613. }
  614. else if(oprNode.data.projType === projectType.engineering){
  615. html += '<p><i class="fa fa-cube"></i> ' + oprNode.data.name + '下的单位工程都将恢复都将恢复,恢复后将重命名为</p>';
  616. }
  617. html += ('<p>');
  618. for(let i = 0, len = nodes.length; i < len; i++){
  619. let recName = nodes[i].data.name + '(' + new Date().Format('MM-dd hh:mm:ss') +'恢复)';
  620. html += '<b>' + recName + '</b>、';
  621. }
  622. html = html.slice(0, html.length - 1);
  623. html += ('</p>');
  624. }
  625. html += ('<p>点“确定”按钮,确认从回收站中恢复</p>');
  626. }
  627. else{
  628. html += ('<p>点“确定”按钮,确认彻底删除数据</p>');
  629. }
  630. return html;
  631. }
  632. //单价、费率文件恢复弹出框数据
  633. function v_getFiles(type, files, tenders, opr = null){
  634. let html = '';
  635. function hasTheFile(tenders, fileId, fileType){
  636. for(let tender of tenders){
  637. let fileAttr = fileType === 'UnitPriceFile' ? 'unitPriceFile' : 'feeFile';
  638. if(tender.data.property[fileAttr]['id'] == fileId){
  639. return true;
  640. }
  641. }
  642. return false;
  643. }
  644. for(let i = 0, len = files.length; i < len; i ++){
  645. let recName = type === fileType.unitPriceFile ? files[i].name + '单价文件' : files[i].name + '费率文件';
  646. let fileId = type === fileType.unitPriceFile ? files[i].id : files[i].ID;
  647. let recTimeA = formatDate(new Date(files[i].deleteInfo.deleteDateTime), 'yyyy-MM-dd');
  648. let recTimeB = formatDate(new Date(files[i].deleteInfo.deleteDateTime), 'HH:mm:ss');
  649. if(opr && opr === 'delete'){
  650. //还被引用,不可删除
  651. if(hasTheFile(tenders, fileId, type)){
  652. html += '<tr><td width="266px">'+ recName +'</td><td width="136px">' + recTimeA + '<br>' + recTimeB + '</td><td width="64px"><input disabled name="fileItems" type="checkbox" fileId = "' + fileId + '" fileType = "' + type + '"></td></tr>';
  653. }
  654. else {
  655. html += '<tr><td width="266px">'+ recName +'</td><td width="136px">' + recTimeA + '<br>' + recTimeB + '</td><td width="64px"><input name="fileItems" type="checkbox" fileId = "' + fileId + '" fileType = "' + type + '"></td></tr>';
  656. }
  657. }
  658. else{
  659. html += '<tr><td width="266px">'+ recName +'</td><td width="136px">' + recTimeA + '<br>' + recTimeB + '</td><td width="64px"><input name="fileItems" type="checkbox" fileId = "' + fileId + '" fileType = "' + type + '"></td></tr>';
  660. }
  661. }
  662. return html;
  663. }
  664. //恢复或清除单价、费率文件后前端显示变化
  665. function v_refreshFiles(project, fileIds, type){
  666. let projFiles;
  667. if(type === fileType.unitPriceFile){
  668. projFiles = project.data.unitPriceFiles;
  669. }
  670. else if(type === fileType.feeRateFile){
  671. projFiles = project.data.feeRateFiles;
  672. }
  673. if(projFiles && projFiles.length > 0){
  674. let tempFiles = [];
  675. for(let i = 0, len = projFiles.length; i < len; i++){
  676. let isExist = false;
  677. for(let j = 0, jLen = fileIds.length; j < jLen; j++){
  678. let id = projFiles[i].id || projFiles[i].ID || null;
  679. if(id && id === fileIds[j]){
  680. isExist = true;
  681. break;
  682. }
  683. }
  684. if(!isExist){
  685. tempFiles.push(projFiles[i]);
  686. }
  687. }
  688. if(type === fileType.unitPriceFile){
  689. project.data.unitPriceFiles = tempFiles;
  690. }
  691. else if(type === fileType.feeRateFile){
  692. project.data.feeRateFiles = tempFiles;
  693. }
  694. }
  695. }
  696. function v_removeNode(node){
  697. gcTreeObj.remove(node);
  698. let parent = node.parent || null;
  699. if(parent && parent.children.length === 0 && parent.data !== undefined){
  700. if(parent.data.projType === projectType.project && fileEmpty(parent)){
  701. v_removeNode(parent);
  702. }
  703. else if(parent.data.projType !== projectType.project){
  704. v_removeNode(parent);
  705. }
  706. }
  707. }
  708. function v_refreshNode(node, recovery = true){
  709. if(recovery){
  710. if(deleted(node)){
  711. delete node.data.deleteInfo;
  712. }
  713. }
  714. gcTreeObj.refreshNodeData(node);
  715. let parent = node.parent || null;
  716. if(parent && parent.data !== undefined){
  717. v_refreshNode(parent, recovery);
  718. }
  719. }
  720. //将获取的回收站中的数据建虚拟树
  721. function m_buildVirtualTree(datas){
  722. for(let i = 0, len = datas.length; i < len; i++){
  723. if(datas[i].projType === projectType.project){
  724. datas[i].ParentID = -1;
  725. }
  726. let children = datas[i].children || null;
  727. if(children){
  728. m_buildVirtualTree(children);
  729. }
  730. let next = datas[i+1] || null;
  731. if(next){
  732. datas[i].NextSiblingID = next.ID;
  733. }
  734. else {
  735. datas[i].NextSiblingID = -1;
  736. }
  737. }
  738. }
  739. function m_VTreeToDatas(datas){
  740. let rst = [];
  741. let projs = datas;
  742. rst = rst.concat(projs);
  743. for(let i = 0, len = projs.length; i < len; i++){
  744. let p_engs = projs[i].children || null;
  745. if(p_engs){
  746. rst = rst.concat(p_engs);
  747. for(let j = 0, jLen = p_engs.length; j < jLen; j ++){
  748. let e_tenders = p_engs[j].children || null;
  749. if(e_tenders){
  750. rst = rst.concat(e_tenders);
  751. }
  752. }
  753. }
  754. }
  755. return rst;
  756. }
  757. //获得当前节点的tenders数据,模态提示框用
  758. function m_getTenders(node){
  759. if(node.data.projType === projectType.tender) return [node];
  760. else {
  761. let rst = [];
  762. if(node.children.length > 0){
  763. node.children.forEach(function (cNode) {
  764. if(cNode.children.length > 0){
  765. cNode.children.forEach(function (ccNode) {
  766. if(ccNode.data.projType === projectType.tender) rst.push(ccNode);
  767. });
  768. }
  769. else if(cNode.children.length === 0 && cNode.data.projType === projectType.tender){
  770. rst.push(cNode);
  771. }
  772. });
  773. }
  774. return rst;
  775. }
  776. }
  777. //获得要更新的数据(包含恢复的数据,维护项目管理树的数据)
  778. function m_getRecDatas(oprNode){
  779. let rst = Object.create(null);
  780. let rstProj = [], rstFile = [];
  781. let path;
  782. if(oprNode.data.projType === projectType.tender){
  783. path = recPath.t;
  784. let engineering = oprNode.parent || null;
  785. if(!engineering) return null;
  786. let project = engineering.parent || null;
  787. if(!project) return null;
  788. if(engineering && deleted(engineering)){
  789. path = recPath.t_e;
  790. }
  791. //恢复建设项目
  792. if(project && deleted(project)){
  793. path = recPath.t_e_p;
  794. }
  795. //恢复单价、费率文件
  796. rstFile = rstFile.concat(getUpdateFiles([oprNode], project));
  797. if(path === recPath.t){
  798. rstProj = rstProj.concat(getUpdateDatas(projectType.tender, oprNode, -1, true));
  799. }
  800. else if(path === recPath.t_e){
  801. rstProj = rstProj.concat(getUpdateDatas(projectType.tender, oprNode, -1, false));
  802. rstProj = rstProj.concat(getUpdateDatas(projectType.engineering, engineering, -1, true));
  803. }
  804. else if(path === recPath.t_e_p){
  805. rstProj = rstProj.concat(getUpdateDatas(projectType.tender, oprNode, -1, false));
  806. rstProj = rstProj.concat(getUpdateDatas(projectType.engineering, engineering, -1, false));
  807. rstProj = rstProj.concat(getUpdateDatas(projectType.project, project, -1, false));
  808. }
  809. }
  810. else if(oprNode.data.projType === projectType.engineering){
  811. path = recPath.e;
  812. let project = oprNode.parent || null;
  813. if(!project) return null;
  814. //恢复建设项目
  815. if(project && deleted(project)){
  816. path = recPath.e_p;
  817. }
  818. let tenders = oprNode.children;
  819. if(tenders.length > 0){
  820. for(let i = 0, len = tenders.length; i < len; i++){
  821. rstProj = rstProj.concat(getUpdateDatas(projectType.tender, tenders[i], tenders[i].data.NextSiblingID, false));
  822. }
  823. rstProj = deWeightName(rstProj);
  824. //恢复单价、费率文件
  825. rstFile = rstFile.concat(getUpdateFiles(tenders, project));
  826. }
  827. if(path === recPath.e){
  828. rstProj= rstProj.concat(getUpdateDatas(projectType.engineering, oprNode, -1, true));
  829. }
  830. else if(path === recPath.e_p){
  831. rstProj= rstProj.concat(getUpdateDatas(projectType.engineering, oprNode, -1, false));
  832. rstProj= rstProj.concat(getUpdateDatas(projectType.project, project, -1, false));
  833. }
  834. }
  835. else if(oprNode.data.projType === projectType.project){
  836. path = recPath.p;
  837. let engineerings = oprNode.children;
  838. if(engineerings.length > 0){
  839. let allTenders = [], rstEngs = [];
  840. for(let i = 0, len = engineerings.length; i < len; i++){
  841. //恢复单项工程
  842. rstEngs = rstEngs.concat(getUpdateDatas(projectType.engineering, engineerings[i], engineerings[i].data.NextSiblingID, false));
  843. let tenders = engineerings[i].children;
  844. allTenders = allTenders.concat(tenders);
  845. let rstTends = [];
  846. for(let j = 0, jLen = tenders.length; j < jLen; j++){
  847. //恢复单位工程
  848. rstTends = rstTends.concat(getUpdateDatas(projectType.tender, tenders[j], tenders[j].data.NextSiblingID, false));
  849. }
  850. //去除重名
  851. rstTends = deWeightName(rstTends);
  852. rstProj = rstProj.concat(rstTends);
  853. }
  854. //去除重名
  855. rstEngs = deWeightName(rstEngs);
  856. rstProj = rstProj.concat(rstEngs);
  857. //恢复单价、费率文件
  858. rstFile = rstFile.concat(getUpdateFiles(allTenders, oprNode));
  859. }
  860. //恢复建设项目
  861. rstProj = rstProj.concat(getUpdateDatas(projectType.project, oprNode, false, false));
  862. }
  863. rst.proj = rstProj;
  864. rst.file = rstFile;
  865. return rst;
  866. }
  867. //获取清除的数据
  868. function m_getDelDatas(oprNode){
  869. let rst = [];
  870. if(!oprNode){
  871. return rst;
  872. }
  873. function getChild(node){
  874. rst.push({updateType: 'Project', ID: node.data.ID});
  875. if(node.children.length > 0){
  876. for(let child of node.children){
  877. getChild(child);
  878. }
  879. }
  880. }
  881. getChild(oprNode);
  882. //父节点只有一个单位工程,则清除此单位工程的时候,父节点也清除,(建设项目单价、费率文件存在时不清除)
  883. if(oprNode.data.projType === projectType.tender){
  884. let eng = oprNode.parent, proj = null;
  885. if(eng && deleted(eng)){
  886. proj = eng.parent;
  887. rst.push({updateType: 'Project', ID: eng.data.ID});
  888. }
  889. if(proj && deleted(proj) && fileEmpty(proj)){
  890. rst.push({updateType: 'Project', ID: proj.data.ID})
  891. }
  892. }
  893. else if(oprNode.data.projType === projectType.engineering){
  894. let proj = oprNode.parent;
  895. if(proj && deleted(proj) && fileEmpty(proj)){
  896. rst.push({updateType: 'Project', ID: proj.data.ID});
  897. }
  898. }
  899. else if(oprNode.data.projType === projectType.project){
  900. for(let uf of oprNode.data.unitPriceFiles){
  901. rst.push({updateType: fileType.unitPriceFile, ID: uf.id});
  902. }
  903. for(let ff of oprNode.data.feeRateFiles){
  904. rst.push({updateType: fileType.feeRateFile, ID: ff.ID});
  905. }
  906. }
  907. return rst;
  908. }
  909. //获得勾选的单价、费率文件的id
  910. function m_getFilesObjs(nodes){
  911. let rst = [];
  912. for(let i = 0, len = nodes.length; i < len; i++){
  913. let fileId = $(nodes[i]).attr('fileId') || null;
  914. if(fileId){
  915. let dispName = $('td:eq(0)', $(nodes[i])[0].parentNode.parentNode)[0].textContent;
  916. let name = dispName.slice(0, dispName.length - 4);
  917. if($(nodes[i]).attr('fileType') === fileType.unitPriceFile){
  918. fileId = parseInt(fileId);
  919. }
  920. let obj = Object.create(null);
  921. obj.id = fileId;
  922. obj.name = name;
  923. rst.push(obj);
  924. }
  925. }
  926. return rst;
  927. }
  928. function m_project(node){
  929. if(node && node.data.projType === projectType.project) return node;
  930. if(!node) return null;
  931. let parent = node.parent || null;
  932. if(!parent) return null;
  933. if(parent && parent.data.projType === projectType.project) return parent;
  934. let gParent = parent.parent || null;
  935. if(!gParent) return null;
  936. if(gParent && gParent.data.projType === projectType.project) return gParent;
  937. return null;
  938. }
  939. //点击单价文件、费率文件下的恢复操作(确认)
  940. function e_recFiles(btn){
  941. btn.bind('click', function () {
  942. decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
  943. let recObjs = m_getFilesObjs($('[name = "fileItems"]:checked'));
  944. let recIds = [];
  945. for(let i of recObjs){
  946. recIds.push(i.id);
  947. }
  948. let type = $('[name = "fileItems"]:checked').attr('fileType');
  949. let selected = gcTreeObj.tree.selected;
  950. //backend
  951. let updateDatas = [];
  952. for(let i = 0, len = recObjs.length; i < len; i++){
  953. let findData = type === fileType.unitPriceFile ? {id: recObjs[i].id} : {ID: recObjs[i].id};
  954. updateDatas.push(getUpdateObj(type, findData, {deleteInfo: null, name: delPostFix(recObjs[i].name) + decDate}));
  955. }
  956. //恢复建设项目
  957. if(updateDatas.length > 0 && deleted(selected)){
  958. updateDatas.push(getUpdateObj(projectType.project, {ID: selected.data.ID}, {deleteInfo: null, name: delPostFix(selected.data.name) + decDate}));
  959. }
  960. updateDatas = deWeightName(updateDatas);
  961. a_rec(updateDatas, caller);
  962. function caller(){
  963. //front
  964. if(recIds.length > 0){
  965. v_refreshFiles(selected, recIds, type);
  966. if(deleted(selected)){
  967. delete selected.data.deleteInfo;
  968. }
  969. if(fileEmpty(selected) && selected.children.length === 0){
  970. gcTreeObj.remove(selected);
  971. }
  972. else {
  973. gcTreeObj.refreshNodeData(selected);
  974. }
  975. }
  976. }
  977. });
  978. }
  979. //点击单价、费率文件的清除操作(确认)
  980. function e_delFiles(btn){
  981. btn.bind('click', function () {
  982. let selected = gcTreeObj.tree.selected;//project
  983. let delObjs = m_getFilesObjs($('[name = "fileItems"]:checked'));
  984. let type = $('[name = "fileItems"]:checked').attr('fileType');
  985. let delDatas = [];
  986. let delIds = [];
  987. for(let delObj of delObjs){
  988. delIds.push(delObj.id);
  989. delDatas.push({updateType: type, ID: delObj.id});
  990. }
  991. //此操作造成了建设项目的文件为空,则清除建设项目
  992. if(fileWillEmpty(selected, delIds, type)){
  993. //delDatas.push({updateType: 'Project', ID: selected.data.ID});
  994. }
  995. if(delDatas.length > 0){
  996. //backend
  997. a_delGC(delDatas, caller);
  998. //front
  999. function caller(){
  1000. v_refreshFiles(selected, delIds, type);
  1001. if(fileEmpty(selected) && selected.children.length === 0){
  1002. gcTreeObj.remove(selected);
  1003. }
  1004. else {
  1005. gcTreeObj.refreshNodeData(selected);
  1006. }
  1007. }
  1008. }
  1009. });
  1010. }
  1011. //点击项目下的恢复操作(确认)
  1012. function e_recProj(btn){
  1013. btn.bind('click', function () {
  1014. let selected = gcTreeObj.tree.selected;
  1015. //backend
  1016. let updateObj = m_getRecDatas(selected);
  1017. let updateDatas = updateObj.proj.concat(updateObj.file);
  1018. let fileObj = getRecFileObj(updateObj.file);
  1019. //保存成功后回调front
  1020. a_rec(updateDatas, caller);
  1021. function caller() {
  1022. let project = m_project(selected);
  1023. if(project){
  1024. if(fileObj[fileType.unitPriceFile].length > 0){
  1025. v_refreshFiles(project, fileObj[fileType.unitPriceFile], fileType.unitPriceFile);
  1026. }
  1027. if(fileObj[fileType.feeRateFile].length > 0){
  1028. v_refreshFiles(project, fileObj[fileType.feeRateFile], fileType.feeRateFile);
  1029. }
  1030. }
  1031. v_removeNode(selected);
  1032. v_refreshNode(selected, true);
  1033. }
  1034. });
  1035. }
  1036. function e_delProj(btn){
  1037. btn.bind('click', function () {
  1038. let selected = gcTreeObj.tree.selected;
  1039. //backend
  1040. let delDatas = m_getDelDatas(selected);
  1041. if(delDatas.length > 0){
  1042. a_delGC(delDatas, caller);
  1043. }
  1044. //front
  1045. function caller() {
  1046. v_removeNode(selected);
  1047. v_refreshNode(selected, false);
  1048. }
  1049. });
  1050. }
  1051. function a_getGC(callback){
  1052. CommonAjax.post('/pm/api/getGCDatas', {user_id: userID}, function (rstData) {
  1053. if(callback){
  1054. callback(rstData);
  1055. }
  1056. });
  1057. }
  1058. function a_rec(nodes, callback){
  1059. CommonAjax.post('/pm/api/recGC', {user_id: userID, nodes: nodes}, function (rstData) {
  1060. if(callback){
  1061. callback();
  1062. }
  1063. });
  1064. }
  1065. function a_delGC(delDatas, callback){
  1066. CommonAjax.post('/pm/api/delGC', {user_id: userID, delDatas: delDatas}, function(rstData){
  1067. if(callback){
  1068. callback();
  1069. }
  1070. })
  1071. }
  1072. //去除重名,回收站不处理重名,只保证恢复到项目管理中不出现重名
  1073. function deWeightName(datas){
  1074. let rst = [];
  1075. let _deWeight = Object.create(null), prefix = 'name_';
  1076. //按同名分组
  1077. for(let i = 0, len = datas.length; i < len; i++){
  1078. let data = datas[i];
  1079. let _names = _deWeight[prefix + data.updateData.name] || null;
  1080. if(!_names){
  1081. _names = _deWeight[prefix + data.updateData.name] = [];
  1082. }
  1083. if(_names){
  1084. _names.push(data);
  1085. }
  1086. }
  1087. for(let _name in _deWeight){
  1088. let sameNameDatas = _deWeight[_name];
  1089. let count = 0;
  1090. for(let i = 0, len = sameNameDatas.length; i < len; i++){
  1091. let postFix = '(' + count + ')';
  1092. if(i > 0){
  1093. sameNameDatas[i].updateData.name = sameNameDatas[i].updateData.name + postFix;
  1094. }
  1095. count ++;
  1096. rst.push(sameNameDatas[i]);
  1097. }
  1098. }
  1099. return rst;
  1100. }
  1101. //去除名称后缀(Date恢复)
  1102. function delPostFix (str){
  1103. let rst = '';
  1104. rst = delPostRecFix(delPostNameFix(str));
  1105. return rst;
  1106. }
  1107. function delPostRecFix (str){
  1108. let rst = '';
  1109. let re = /(+[0-9]{2}-[0-9]{2}\s+[0-9]{2}:[0-9]{2}:[0-9]{2}恢复)/g;
  1110. rst = str.replace(re, '');
  1111. return rst;
  1112. }
  1113. function delPostNameFix (str){
  1114. let rst = '';
  1115. let re = /(+[0-9][0-9]*)/g;
  1116. rst = str.replace(re, '');
  1117. return rst;
  1118. }
  1119. function deleted(node){
  1120. return node.data.deleteInfo !== undefined && node.data.deleteInfo && node.data.deleteInfo.deleted;
  1121. }
  1122. function fileEmpty(node){
  1123. return node.data.unitPriceFiles.length === 0 && node.data.feeRateFiles.length === 0;
  1124. }
  1125. function fIsExist(files, id, type){
  1126. let isExist = false;
  1127. for(let i = 0, len = files.length; i < len; i++){
  1128. if((type === fileType.unitPriceFile && files[i].id === parseInt(id)) || (type === fileType.feeRateFile && files[i].ID === id)){
  1129. isExist = true;
  1130. break;
  1131. }
  1132. }
  1133. return isExist;
  1134. }
  1135. //删除的文件是否会导致建设项目不再存有文件
  1136. function fileWillEmpty(proj, delIds, type){
  1137. let ufs = proj.data.unitPriceFiles,
  1138. ffs = proj.data.feeRateFiles;
  1139. let theFiles = type === fileType.unitPriceFile ? ufs : ffs;
  1140. otherFiles = type === fileType.unitPriceFile ? ffs : ufs;
  1141. let uniqIds = Array.from(new Set(delIds));
  1142. if(theFiles.length === delIds.length){
  1143. for(let id of uniqIds){
  1144. if(!fIsExist(theFiles, id, type)){
  1145. return false;
  1146. }
  1147. }
  1148. }
  1149. if(otherFiles.length === 0){
  1150. return true;
  1151. }
  1152. return false;
  1153. }
  1154. function getRecFileObj(files){
  1155. let rst = Object.create(null);
  1156. let rst_UF = [], rst_FF = [];
  1157. for(let i = 0, len = files.length; i < len; i++){
  1158. if(files[i].findData !== undefined){
  1159. if(files[i].updateType === fileType.unitPriceFile && files[i].findData.id !== undefined){
  1160. rst_UF.push(files[i].findData.id);
  1161. }
  1162. else if(files[i].updateType === fileType.feeRateFile && files[i].findData.ID !== undefined){
  1163. rst_FF.push(files[i].findData.ID);
  1164. }
  1165. }
  1166. }
  1167. rst[fileType.unitPriceFile] = rst_UF;
  1168. rst[fileType.feeRateFile] = rst_FF;
  1169. return rst;
  1170. }
  1171. function getUpdateObj(updateType, findData, updateData){
  1172. let obj = Object.create(null);
  1173. obj.updateType = updateType;
  1174. obj.findData = findData;
  1175. obj.updateData = updateData;
  1176. return obj;
  1177. }
  1178. function getUpdateDatas(updateType, node, mtNID, mtPM){
  1179. let rst = [];
  1180. decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
  1181. let newName = delPostFix(node.data.name) + decDate;
  1182. if(updateType === projectType.tender || updateType === projectType.engineering){
  1183. //维护项目管理树
  1184. if(mtPM){
  1185. rst.push(getUpdateObj(updateType, {ParentID: node.data.ParentID, NextSiblingID: -1, deleteInfo: null}, {NextSiblingID: node.data.ID}));
  1186. }
  1187. //恢复
  1188. if(mtNID){
  1189. rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {name: newName, deleteInfo: null, NextSiblingID: mtNID}));
  1190. }
  1191. else {
  1192. rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {name: newName, deleteInfo: null}));
  1193. }
  1194. }
  1195. else if(updateType === projectType.project){
  1196. //恢复
  1197. rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {deleteInfo: null, name: newName}));//NextSibling为undefined,后端处理
  1198. }
  1199. return rst;
  1200. }
  1201. //unitPriceFile or feeRateFile
  1202. function getUpdateFiles(tenders, project){
  1203. let rstUF = [], rstFF = [], rst = [];
  1204. let _unitFiles = Object.create(null), _feeFiles = Object.create(null), prefix = '_id';
  1205. decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
  1206. for(let i = 0, len = tenders.length; i < len; i++){
  1207. //恢复单价文件
  1208. if(project && project.data.unitPriceFiles.length > 0 && fIsExist(project.data.unitPriceFiles, tenders[i].data.property.unitPriceFile.id, fileType.unitPriceFile)){
  1209. //unitFiles.push(tenders[i].data.property.unitPriceFile.id);
  1210. let propId = tenders[i].data.property.unitPriceFile.id;
  1211. let propName = tenders[i].data.property.unitPriceFile.name;
  1212. let _uf = _unitFiles[prefix + propId] || null;
  1213. if(!_uf){
  1214. let obj = Object.create(null);
  1215. obj.id = parseInt(propId);
  1216. obj.name = propName;
  1217. _unitFiles[prefix + propId] = obj;
  1218. }
  1219. }
  1220. //恢复费率文件
  1221. if(project && project.data.feeRateFiles.length > 0 && fIsExist(project.data.feeRateFiles, tenders[i].data.property.feeFile.id, fileType.feeRateFile)){
  1222. //feeFiles.push(tenders[i].data.property.feeFile.id);
  1223. let propId = tenders[i].data.property.feeFile.id;
  1224. let propName = tenders[i].data.property.feeFile.name;
  1225. let _ff = _feeFiles[prefix + propId] || null;
  1226. if(!_ff){
  1227. let obj = Object.create(null);
  1228. obj.id = propId;
  1229. obj.name = propName;
  1230. _feeFiles[prefix + propId] = obj;
  1231. }
  1232. }
  1233. }
  1234. for(let uf in _unitFiles){
  1235. rstUF.push(getUpdateObj(fileType.unitPriceFile, {id: _unitFiles[uf].id}, {deleteInfo: null, name: delPostFix(_unitFiles[uf].name) + decDate}));
  1236. }
  1237. for(let ff in _feeFiles){
  1238. rstFF.push(getUpdateObj(fileType.feeRateFile, {ID: _feeFiles[ff].id}, {deleteInfo: null, name: delPostFix(_feeFiles[ff].name) + decDate}));
  1239. }
  1240. rst = rst.concat(deWeightName(rstUF));
  1241. rst = rst.concat(deWeightName(rstFF));
  1242. return rst;
  1243. }