ledger.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /**
  2. * 台账相关js
  3. *
  4. * @author Mai
  5. * @date 2018/02/05
  6. * @version
  7. */
  8. $(document).ready(function() {
  9. autoFlashHeight();
  10. const ledgerSpread = SpreadJsObj.createNewSpread($('#ledger-spread')[0]);
  11. SpreadJsObj.addDeleteBind(ledgerSpread);
  12. const ledgerTree = createNewPathTree({
  13. id: 'ledger_id',
  14. pid: 'ledger_pid',
  15. order: 'order',
  16. level: 'level',
  17. rootId: -1,
  18. keys: ['id', 'tender_id', 'ledger_id']
  19. });
  20. ledgerTree.loadDatas(ledger);
  21. SpreadJsObj.initSheet(ledgerSpread.getActiveSheet(), {
  22. cols: [
  23. {title: '项目节编号', field: 'code', width: 150, cellType: 'tree'},
  24. {title: '清单编号', field: 'b_code', width: 80},
  25. {title: '名称', field: 'name', width: 230},
  26. {title: '单位', field: 'unit', width: 50},
  27. {title: '单价', field: 'unit_price', width: 60, type: 'Number'},
  28. {title: '数量', field: 'quantity', width: 60, type: 'Number'},
  29. {title: '金额', field: 'total_price', width: 60, type: 'Number'},
  30. {title: '施工图原设计', field: 'design', width: 60},
  31. {title: '图(册)号', field: 'drawingCode', width: 80},
  32. {title: '备注', field: 'memo', width: 100}
  33. ],
  34. treeCol: 0,
  35. emptyRows: 3
  36. });
  37. SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
  38. const treeOperationObj = {
  39. /**
  40. * 刷新顶部按钮是否可用
  41. * @param sheet
  42. * @param selections
  43. */
  44. refreshOperationValid: function (sheet, selections) {
  45. const setObjEnable = function (obj, enable) {
  46. if (enable) {
  47. obj.removeClass('disabled');
  48. } else {
  49. obj.addClass('disabled');
  50. }
  51. };
  52. const row = selections[0].row;
  53. const tree = sheet.zh_tree;
  54. if (!tree) { return; }
  55. const node = sheet.zh_tree.nodes[row];
  56. setObjEnable($('#delete'), node);
  57. setObjEnable($('#up-move'), node && node.order > 1);
  58. setObjEnable($('#down-move'), node && !tree.isLastSibling(node));
  59. setObjEnable($('#up-level'), tree.getParent(node));
  60. setObjEnable($('#down-level'), node && node.order > 1);
  61. },
  62. /**
  63. * 新增节点
  64. * @param spread
  65. */
  66. addNode: function (spread) {
  67. const self = this;
  68. const sheet = spread.getActiveSheet();
  69. const row = sheet.getSelections()[0].row;
  70. const tree = sheet.zh_tree;
  71. if (!tree) { return; }
  72. const node = sheet.zh_tree.nodes[row];
  73. if (!node) { return; }
  74. SpreadJsObj.massOperationSheet(sheet, function () {
  75. tree.baseOperation('base-operation', node, 'add', function (result) {
  76. const newNodes = result.create;
  77. if (newNodes) {
  78. newNodes.sort(function (a, b) {
  79. const aIndex = tree.nodes.indexOf(a);
  80. const bIndex = tree.nodes.indexOf(b);
  81. return aIndex - bIndex;
  82. });
  83. for (const node of newNodes) {
  84. const index = tree.nodes.indexOf(node);
  85. sheet.addRows(index, 1);
  86. }
  87. }
  88. self.refreshOperationValid(sheet, sheet.getSelections());
  89. });
  90. });
  91. },
  92. /**
  93. * 删除选中节点
  94. * @param spread
  95. */
  96. deleteNode: function (spread) {
  97. const self = this;
  98. const sheet = spread.getActiveSheet();
  99. const row = sheet.getSelections()[0].row;
  100. const tree = sheet.zh_tree;
  101. if (!tree) { return; }
  102. const node = sheet.zh_tree.nodes[row];
  103. if (!node) { return; }
  104. const count = ledgerTree.getPosterity(node).length;
  105. tree.baseOperation('base-operation', node, 'delete', function (result) {
  106. sheet.deleteRows(row, count + 1);
  107. for (const data of result.update) {
  108. SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(data), tree.getPosterity(data).length + 1);
  109. }
  110. self.refreshOperationValid(sheet, sheet.getSelections());
  111. });
  112. },
  113. /**
  114. * 上移选中节点
  115. * @param spread
  116. */
  117. upMove: function (spread) {
  118. const self = this;
  119. const sheet = spread.getActiveSheet();
  120. const sel = sheet.getSelections()[0];
  121. const row = sel.row;
  122. const tree = sheet.zh_tree;
  123. if (!tree) { return; }
  124. const node = tree.nodes[row];
  125. if (!node) { return; }
  126. tree.baseOperation('base-operation', node, 'up-move', function (result) {
  127. for (const data of result.update) {
  128. SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(data), tree.getPosterity(data).length + 1);
  129. }
  130. sheet.setSelection(tree.nodes.indexOf(node), sel.col, sel.rowCount, sel.colCount);
  131. self.refreshOperationValid(sheet, sheet.getSelections());
  132. //sheet.moveTo(row, -1, tree.nodes.indexOf(node), -1, tree.getPosterity(node).length + 1, -1, GC.Spread.Sheets.CopyToOptions.value);
  133. });
  134. },
  135. /**
  136. * 下移选中节点
  137. * @param spread
  138. */
  139. downMove: function (spread) {
  140. const self = this;
  141. const sheet = spread.getActiveSheet();
  142. const sel = sheet.getSelections()[0];
  143. const row = sel.row;
  144. const tree = sheet.zh_tree;
  145. if (!tree) { return; }
  146. const node = tree.nodes[row];
  147. if (!node) { return; }
  148. tree.baseOperation('base-operation', node, 'down-move', function (result) {
  149. for (const data of result.update) {
  150. SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(data), tree.getPosterity(data).length + 1);
  151. }
  152. sheet.setSelection(tree.nodes.indexOf(node), sel.col, sel.rowCount, sel.colCount);
  153. self.refreshOperationValid(sheet, sheet.getSelections());
  154. });
  155. },
  156. /**
  157. * 升级选中节点
  158. * @param spread
  159. */
  160. upLevel: function (spread) {
  161. const self = this;
  162. const sheet = spread.getActiveSheet();
  163. const row = sheet.getSelections()[0].row;
  164. const tree = sheet.zh_tree;
  165. if (!tree) { return; }
  166. const node = tree.nodes[row];
  167. if (!node) { return; }
  168. tree.baseOperation('base-operation', node, 'up-level', function (result) {
  169. const rows = [];
  170. for (const u of result.update) {
  171. rows.push(tree.nodes.indexOf(u));
  172. }
  173. SpreadJsObj.reLoadRowsData(sheet, rows);
  174. self.refreshOperationValid(sheet, sheet.getSelections());
  175. });
  176. },
  177. /**
  178. * 降级选中节点
  179. * @param spread
  180. */
  181. downLevel: function (spread) {
  182. const self = this;
  183. const sheet = spread.getActiveSheet();
  184. const row = sheet.getSelections()[0].row;
  185. const tree = sheet.zh_tree;
  186. if (!tree) { return; }
  187. const node = tree.nodes[row];
  188. if (!node) { return; }
  189. tree.baseOperation('base-operation', node, 'down-level', function (result) {
  190. const rows = [];
  191. for (const u of result.update) {
  192. rows.push(tree.nodes.indexOf(u));
  193. }
  194. SpreadJsObj.reLoadRowsData(sheet, rows);
  195. self.refreshOperationValid(sheet, sheet.getSelections());
  196. });
  197. },
  198. /**
  199. * 编辑单元格响应事件
  200. * @param {Object} e
  201. * @param {Object} info
  202. */
  203. editEnded: function (e, info) {
  204. if (info.sheet.zh_setting) {
  205. const col = info.sheet.zh_setting.cols[info.col];
  206. const sortData = info.sheet.zh_dataType === 'tree' ? info.sheet.zh_tree.nodes : info.sheet.zh_data;
  207. const node = sortData[info.row];
  208. const data = {
  209. id: node.id,
  210. tender_id: node.tender_id,
  211. ledger_id: node.ledger_id
  212. };
  213. data[col.field] = col.type === 'Number' ? parseFloat(info.editingText) : info.editingText;
  214. info.sheet.zh_tree.update('update', data, function (result) {
  215. const rows = [];
  216. for (const r of result) {
  217. rows.push(sortData.indexOf(r));
  218. }
  219. SpreadJsObj.reLoadRowsData(info.sheet, rows);
  220. });
  221. }
  222. },
  223. /**
  224. * 粘贴单元格响应事件
  225. * @param e
  226. * @param info
  227. */
  228. clipboardPasted: function (e, info) {
  229. if (info.sheet.zh_setting && info.sheet.zh_dataType === 'tree') {
  230. const sortData = info.sheet.zh_tree.nodes;
  231. const datas = [], nodes = [];
  232. for (let iRow = 0; iRow < info.cellRange.rowCount; iRow ++) {
  233. const curRow = info.cellRange.row + iRow;
  234. const node = sortData[curRow];
  235. if (node) {
  236. const data = info.sheet.zh_tree.getNodeKeyData(node);
  237. for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
  238. const curCol = info.cellRange.col + iCol;
  239. const colSetting = info.sheet.zh_setting.cols[curCol];
  240. data[colSetting.field] = info.sheet.getText(curRow, curCol);
  241. }
  242. datas.push(data);
  243. nodes.push(node);
  244. }
  245. }
  246. info.sheet.zh_tree.update('update', datas, function (result) {
  247. const rows = [];
  248. for (const data of result) {
  249. rows.push(sortData.indexOf(data));
  250. }
  251. SpreadJsObj.reLoadRowsData(info.sheet, rows);
  252. });
  253. }
  254. },
  255. /**
  256. * 删除按钮响应事件
  257. * @param sheet
  258. */
  259. deletePress: function (sheet) {
  260. if (sheet.zh_setting && sheet.zh_dataType === 'tree') {
  261. const sortData = sheet.zh_tree.nodes;
  262. const datas = [], nodes = [];
  263. const sel = sheet.getSelections()[0];
  264. for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow++) {
  265. const node = sortData[iRow];
  266. if (node) {
  267. const data = sheet.zh_tree.getNodeKeyData(node);
  268. for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
  269. const colSetting = sheet.zh_setting.cols[iCol];
  270. data[colSetting.field] = null;
  271. }
  272. datas.push(data);
  273. nodes.push(node);
  274. }
  275. }
  276. sheet.zh_tree.update('update-info', datas, function (result) {
  277. const rows = [];
  278. for (const data of result) {
  279. rows.push(sortData.indexOf(data));
  280. }
  281. SpreadJsObj.reLoadRowsData(sheet, rows);
  282. });
  283. }
  284. },
  285. /**
  286. * 粘贴整块
  287. * @param spread
  288. * @param block
  289. */
  290. pasteBlock: function (spread, block) {
  291. const self = this;
  292. const sheet = spread.getActiveSheet();
  293. const row = sheet.getSelections()[0].row;
  294. const tree = sheet.zh_tree;
  295. if (!tree) { return; }
  296. const node = tree.nodes[row];
  297. if (!node) { return; }
  298. tree.pasteBlock('paste-block', node, block, function (result) {
  299. SpreadJsObj.massOperationSheet(sheet, function () {
  300. // 新增
  301. const newNodes = result.create;
  302. if (newNodes) {
  303. newNodes.sort(function (a, b) {
  304. const aIndex = tree.nodes.indexOf(a);
  305. const bIndex = tree.nodes.indexOf(b);
  306. return aIndex - bIndex;
  307. });
  308. for (const node of newNodes) {
  309. const index = tree.nodes.indexOf(node);
  310. sheet.addRows(index, 1);
  311. SpreadJsObj.reLoadRowData(sheet, index, 1);
  312. }
  313. }
  314. // 更新
  315. const rows = [];
  316. for (const data of result.update) {
  317. rows.push(tree.nodes.indexOf(data));
  318. }
  319. SpreadJsObj.reLoadRowsData(sheet, rows);
  320. self.refreshOperationValid(sheet, sheet.getSelections());
  321. });
  322. });
  323. }
  324. };
  325. ledgerSpread.bind(GC.Spread.Sheets.Events.SelectionChanged, function (e, info) {
  326. treeOperationObj.refreshOperationValid(info.sheet, info.newSelections);
  327. });
  328. ledgerSpread.bind(GC.Spread.Sheets.Events.EditEnded, treeOperationObj.editEnded);
  329. ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardPasted, treeOperationObj.clipboardPasted);
  330. SpreadJsObj.addDeleteBind(ledgerSpread, treeOperationObj.deletePress);
  331. ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardChanging, function (e, info) {
  332. info.copyData.html = SpreadJsObj.getFilterCopyHTML(info.sheet);
  333. info.copyData.text = SpreadJsObj.getFilterCopyText(info.sheet);
  334. console.log(info.copyData.text);
  335. });
  336. ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardChanged, function (e, info) {
  337. console.log(info.copyData.text);
  338. });
  339. ledgerSpread.bind(GC.Spread.Sheets.Events.ClipboardPasting, function (e, info) {
  340. console.log(info.pasteData.text);
  341. });
  342. // 绑定 删除等 顶部按钮
  343. $('#delete').click(function () {
  344. treeOperationObj.deleteNode(ledgerSpread);
  345. });
  346. $('#up-move').click(function () {
  347. treeOperationObj.upMove(ledgerSpread);
  348. });
  349. $('#down-move').click(function () {
  350. treeOperationObj.downMove(ledgerSpread);
  351. });
  352. $('#up-level').click(function () {
  353. treeOperationObj.upLevel(ledgerSpread);
  354. });
  355. $('#down-level').click(function () {
  356. treeOperationObj.downLevel(ledgerSpread);
  357. });
  358. treeOperationObj.refreshOperationValid(ledgerSpread.getActiveSheet(), ledgerSpread.getActiveSheet().getSelections());
  359. // 右键菜单
  360. $.contextMenu({
  361. selector: '#ledger-spread',
  362. build: function ($trigger, e) {
  363. const target = SpreadJsObj.safeRightClickSelection($trigger, e, ledgerSpread);
  364. return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
  365. },
  366. items: {
  367. 'create': {
  368. name: '新增',
  369. icon: 'fa-sign-in',
  370. callback: function (key, opt) {
  371. treeOperationObj.addNode(ledgerSpread);
  372. },
  373. visible: function(key, opt){
  374. const sheet = ledgerSpread.getActiveSheet();
  375. const selection = sheet.getSelections();
  376. const row = selection[0].row;
  377. const select = ledgerTree.nodes[row];
  378. return select;
  379. }
  380. },
  381. 'delete': {
  382. name: '删除',
  383. icon: 'fa-remove',
  384. callback: function (key, opt) {
  385. treeOperationObj.deleteNode(ledgerSpread);
  386. },
  387. visible: function (key, opt) {
  388. const sheet = ledgerSpread.getActiveSheet();
  389. const selection = sheet.getSelections();
  390. const row = selection[0].row;
  391. const select = ledgerTree.nodes[row];
  392. return select;
  393. }
  394. },
  395. 'copyBlock': {
  396. name: '复制整块',
  397. icon: 'fa-files-o',
  398. callback: function (key, opt) {
  399. /*ledgerSpread.commandManager().execute({
  400. cmd:"copy",
  401. sheetName:ledgerSpread.getActiveSheet().name()
  402. });*/
  403. treeOperationObj.block = [];
  404. const copyBlockList = [];
  405. const sheet = ledgerSpread.getActiveSheet();
  406. const sel = sheet.getSelections()[0];
  407. let iRow = sel.row;
  408. const pid = sheet.zh_tree.nodes[iRow].ledger_pid;
  409. while (iRow < sel.row + sel.rowCount) {
  410. const node = sheet.zh_tree.nodes[iRow];
  411. if (node.ledger_pid !== pid) {
  412. toast('error: 仅可同时选中同层节点', 'error', 'exclamation-circle');
  413. return;
  414. }
  415. copyBlockList.push(node.ledger_id);
  416. iRow += sheet.zh_tree.getPosterity(node).length + 1;
  417. }
  418. treeOperationObj.block = copyBlockList;
  419. },
  420. visible: function (key, opt) {
  421. const sheet = ledgerSpread.getActiveSheet();
  422. const selection = sheet.getSelections();
  423. const row = selection[0].row;
  424. const select = ledgerTree.nodes[row];
  425. return select;
  426. }
  427. },
  428. 'pasteBlock': {
  429. name: '粘贴',
  430. icon: 'fa-clipboard',
  431. disabled: function (key, opt) {
  432. const block = treeOperationObj.block || [];
  433. return block.length <= 0 && false;
  434. },
  435. callback: function (key, opt) {
  436. const block = treeOperationObj.block || [];
  437. if (block.length > 0) {
  438. treeOperationObj.pasteBlock(ledgerSpread, block);
  439. } else {
  440. document.execCommand('paste');
  441. }
  442. }
  443. }
  444. }
  445. });
  446. });