pm_gc.js 52 KB

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