pm_gc.js 56 KB

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