budgetSummarySheet.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /* 建设其他费表格相关 */
  2. const budgetSummaryObj = (() => {
  3. const { isEmptyVal, isDef, isNumber } = window.commonUtil;
  4. const { fixedFlag, BudgetArea } = window.commonConstants;
  5. // 原始数据
  6. let rawData = [];
  7. // 建设其他费表格对象
  8. let spread = null;
  9. // 建设其他费树
  10. let tree = null;
  11. // 计算相关
  12. const calcSetting = {
  13. costGrowthRate: 0,
  14. growthPeriod: 0,
  15. };
  16. // 单位设置下拉框
  17. const setUnitCombo = (sheet, data) => {
  18. const unitCol = budgetSummaryTreeSetting.cols.findIndex(item => item.data.field === 'unit');
  19. if (unitCol >= 0) {
  20. TREE_SHEET_HELPER.massOperationSheet(sheet, () => {
  21. const comboBox = sheetCommonObj.getDynamicCombo();
  22. comboBox
  23. .itemHeight(10)
  24. .items(['m', 'm2', 'm3', 'km', 't', 'kg', '台班', '工日', '昼夜', '元', '项', '处', '个', '件',
  25. '根', '组', '系统', '台', '套', '株', '丛', '缸', '支', '只', '块', '座', '对', '份', '樘', '攒', '榀'])
  26. .editable(true);
  27. data.forEach((item, index) => {
  28. sheet.getCell(index, unitCol).cellType(comboBox);
  29. })
  30. });
  31. }
  32. }
  33. const getFieldByCol = (col) => {
  34. const item = budgetSummaryTreeSetting.cols[col];
  35. return item && item.data && item.data.field || null;
  36. }
  37. // 单元格值验证器
  38. const validator = {
  39. text() {
  40. return true
  41. },
  42. number(val) {
  43. return !isDef(val) || isNumber(val);
  44. },
  45. };
  46. const getValidator = (col) => {
  47. const item = budgetSummaryTreeSetting.cols[col];
  48. if (!item) {
  49. return 'text';
  50. }
  51. return validator[item.data.type || 'text'];
  52. }
  53. /* 表格事件相关 */
  54. // 恢复数据
  55. const recover = (sheet, changedCells) => {
  56. if (!tree) {
  57. return;
  58. }
  59. changedCells.forEach(({ row, col }) => {
  60. const node = tree.items[row];
  61. const field = getFieldByCol(col);
  62. if (!field || !node) {
  63. return;
  64. }
  65. const orgVal = node.data[field];
  66. sheet.setValue(row, col, orgVal);
  67. })
  68. }
  69. // 更新数据
  70. const bulkOperation = async (bulkData) => {
  71. await ajaxPost('/bills/bulkOperation', { bulkData });
  72. };
  73. // 计算节点
  74. const calcNodes = async (sheet, nodes) => {
  75. try {
  76. $.bootstrapLoading.start();
  77. debugger;
  78. const changedNodes = projectObj.project.calcProgram.calcNodes(nodes, false);
  79. const dataArr = [];
  80. for (const node of changedNodes) {
  81. if (node.changed) {
  82. const data = calcTools.cutNodeForSave(node);
  83. dataArr.push(data);
  84. }
  85. }
  86. console.log(dataArr);
  87. } catch (err) {
  88. alert(err);
  89. } finally {
  90. $.bootstrapLoading.end();
  91. }
  92. }
  93. // 编辑相关
  94. const edit = async (sheet, changedCells) => {
  95. if (!changedCells.length) {
  96. return;
  97. }
  98. // 单元格值验证
  99. const isValid = changedCells.every(({ row, col }) => {
  100. const val = sheet.getValue(row, col);
  101. return getValidator(col)(val);
  102. });
  103. // 验证不通过,恢复
  104. if (!isValid) {
  105. recover(sheet, changedCells);
  106. }
  107. let needCalc = false;
  108. const nodes = [];
  109. try {
  110. $.bootstrapLoading.start();
  111. const IDMap = {};
  112. const bulkData = [];
  113. changedCells.forEach(({ row, col }) => {
  114. const node = tree.items[row];
  115. if (!node) {
  116. return;
  117. }
  118. if (!nodes.find(n => n.data.ID !== node.data.ID)) {
  119. nodes.push(node);
  120. }
  121. const field = getFieldByCol(col);
  122. const value = sheet.getValue(row, col) || '';
  123. if (field === 'calcBase') {
  124. debugger;
  125. node.data.userCalcBase = value;
  126. projectObj.project.calcBase.calculate(node, null, false);
  127. if (!projectObj.project.calcBase.success) {
  128. throw projectObj.project.calcBase.errMsg;
  129. }
  130. }
  131. const data = (IDMap[node.data.ID] || (IDMap[node.data.ID] = {}));
  132. data[field] = value;
  133. if (['quantity', 'feesIndex.common.unitFee', 'calcBase', 'feeRate'].includes(field)) {
  134. needCalc = true;
  135. }
  136. });
  137. Object
  138. .entries(IDMap)
  139. .forEach(([ID, data]) => {
  140. bulkData.push({ type: 'update', data: { ID, ...data } });
  141. });
  142. await bulkOperation(bulkData);
  143. bulkData.forEach(item => {
  144. const node = tree.findNode(item.data.ID);
  145. Object.assign(node.data, item.data);
  146. });
  147. // 重算节点
  148. /* if (needCalc && nodes.length) {
  149. await calcNodes(sheet, nodes);
  150. } */
  151. } catch (err) {
  152. recover(sheet, changedCells);
  153. alert(err);
  154. } finally {
  155. $.bootstrapLoading.end();
  156. }
  157. }
  158. // 是否是属于工程费用区域的节点
  159. const isConstructionFeeArea = (node) => {
  160. return node && node.data && node.data.area === BudgetArea.CONSTRUCTION_FEE;
  161. }
  162. // 工具栏可操作性
  163. let upLevelDisabled = false;
  164. let downLevelDisabled = false;
  165. let upMoveDisabled = false;
  166. let downMoveDisabled = false;
  167. const refreshToolsBar = (node) => {
  168. upLevelDisabled = !node || !node.canUpLevel() || isConstructionFeeArea(node) || (node.nextSibling && node.data.calcBase);
  169. downLevelDisabled = !node || !node.canDownLevel() || isConstructionFeeArea(node) || isConstructionFeeArea(node.preSibling) || (node.preSibling && node.preSibling.data.calcBase);
  170. upMoveDisabled = !node || !node.canUpMove() || isConstructionFeeArea(node) || isConstructionFeeArea(node.preSibling);
  171. downMoveDisabled = !node || !node.canDownMove() || isConstructionFeeArea(node) || isConstructionFeeArea(node.nextSibling);
  172. if (upLevelDisabled) {
  173. $('#budget-upLevel').addClass('disabled');
  174. } else {
  175. $('#budget-upLevel').removeClass('disabled');
  176. }
  177. if (downLevelDisabled) {
  178. $('#budget-downLevel').addClass('disabled');
  179. } else {
  180. $('#budget-downLevel').removeClass('disabled');
  181. }
  182. if (upMoveDisabled) {
  183. $('#budget-upMove').addClass('disabled');
  184. } else {
  185. $('#budget-upMove').removeClass('disabled');
  186. }
  187. if (downMoveDisabled) {
  188. $('#budget-downMove').addClass('disabled');
  189. } else {
  190. $('#budget-downMove').removeClass('disabled');
  191. }
  192. };
  193. // 表格选中相关
  194. const selectCell = (row, col, setCell = false) => {
  195. const node = tree.items[row];
  196. refreshToolsBar(node);
  197. tree.selected = node;
  198. console.log(node);
  199. const sheet = spread.getSheet(0);
  200. if (setCell) {
  201. sheet.setActiveCell(row, col);
  202. }
  203. //设置选中行底色和恢复前选中行底色
  204. const refreshNodes = [node];
  205. if (!tree.preSelected) {
  206. refreshNodes.push(tree.items[0]);
  207. } else {
  208. refreshNodes.push(tree.preSelected);
  209. }
  210. tree.preSelected = node;
  211. projectObj.setNodesStyle(sheet, refreshNodes, tree);
  212. };
  213. // 事件列表
  214. const events = {
  215. EnterCell(sender, args) {
  216. args.sheet.repaint();
  217. },
  218. SelectionChanged(sender, args) {
  219. const newSel = args.newSelections[0] ? { row: args.newSelections[0].row, col: args.newSelections[0].col } : { row: 0, col: 0 };
  220. selectCell(newSel.row, newSel.col);
  221. },
  222. ValueChanged(sender, args) {
  223. if (isEmptyVal(args.oldValue) && isEmptyVal(args.newValue)) {
  224. return;
  225. }
  226. edit(args.sheet, [{ row: args.row, col: args.col }]);
  227. },
  228. RangeChanged(sender, args) {
  229. edit(args.sheet, args.changedCells);
  230. }
  231. }
  232. const bindEvents = (sheet) => {
  233. Object.entries(events).forEach(([ev, evFunc]) => {
  234. sheet.bind(GC.Spread.Sheets.Events[ev], evFunc);
  235. });
  236. }
  237. /* 只读相关 */
  238. // 单元格锁定判断
  239. const lockFactory = {
  240. code(node) {
  241. return !!(node && node.getFlag());
  242. },
  243. name(node) {
  244. return !!(node && node.getFlag());
  245. },
  246. calcBase(node) {
  247. return !!(node && node.children.length);
  248. },
  249. feeRate(node) {
  250. return !!(node && node.children.length);
  251. }
  252. };
  253. const lockData = (sheet, nodes, isMass = true) => {
  254. const lock = () => {
  255. if (projectReadOnly) {
  256. sheet.getRange(0, 0, nodes.length, budgetSummaryTreeSetting.cols.length, GC.Spread.Sheets.SheetArea.viewport).locked(true);
  257. return 0;
  258. }
  259. // 工程费用区域,只读
  260. const equipmentNode = nodes.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_EQUIPMENT_FEE);
  261. if (!equipmentNode) {
  262. return 0;
  263. }
  264. sheet.getRange(0, 0, equipmentNode.serialNo() + 1, budgetSummaryTreeSetting.cols.length, GC.Spread.Sheets.SheetArea.viewport).locked(true);
  265. return equipmentNode.serialNo() + 1;
  266. }
  267. if (isMass) {
  268. TREE_SHEET_HELPER.massOperationSheet(sheet, () => {
  269. return lock();
  270. });
  271. } else {
  272. return lock();
  273. }
  274. }
  275. /* 单元格类型 */
  276. const calcBaseButtonCallback = (hitInfo) => {
  277. calcBaseView.onCalcBaseButtonClick(hitInfo, 'budget');
  278. };
  279. const cellTypeFactory = {
  280. calcBase(node) {
  281. const locked = lockFactory.calcBase(node);
  282. return sheetCommonObj.getCusButtonCellType(calcBaseButtonCallback, locked);
  283. }
  284. }
  285. /* 设置可编辑区域节点的只读性和单元格类型 */
  286. const setCells = (sheet, startRow, nodes) => {
  287. for (let row = startRow; row < nodes.length; row++) {
  288. const node = nodes[row];
  289. budgetSummaryTreeSetting.cols.forEach((item, col) => {
  290. const field = item.data.field;
  291. // 锁定单元格
  292. const lockFunc = lockFactory[field];
  293. if (lockFunc) {
  294. const isLocked = lockFunc(node);
  295. sheet.getCell(row, col).locked(isLocked);
  296. }
  297. // 设置单元格类型
  298. const cellTypeFunc = cellTypeFactory[field];
  299. if (cellTypeFunc) {
  300. const cellType = cellTypeFunc(node);
  301. sheet.getCell(row, col).cellType(cellType);
  302. }
  303. });
  304. }
  305. }
  306. /* 初始化表格 */
  307. const initSpread = () => {
  308. if (!spread) {
  309. // spread = sheetCommonObj.createSpread($('#budget-summary-sheet')[0], 1);
  310. spread = SheetDataHelper.createNewSpread($('#budget-summary-sheet')[0]);
  311. sheetCommonObj.spreadDefaultStyle(spread);
  312. // 设置表头
  313. const sheet = spread.getSheet(0);
  314. bindEvents(sheet);
  315. const headers = sheetCommonObj.getHeadersFromTreeSetting(budgetSummaryTreeSetting);
  316. sheetCommonObj.setHeader(sheet, headers);
  317. // 右键菜单
  318. initContextMenu();
  319. } else {
  320. spread.refresh();
  321. }
  322. return spread;
  323. }
  324. // 初始化树
  325. const initTree = (data, sheet, setting) => {
  326. tree = idTree.createNew({ id: 'ID', pid: 'ParentID', nid: 'NextSiblingID', rootId: -1, autoUpdate: true });
  327. const controller = TREE_SHEET_CONTROLLER.createNew(tree, sheet, setting, false, true);
  328. tree.loadDatas(data);
  329. tree.items.forEach(node => {
  330. node.source = node;
  331. node.sourceType = ModuleNames.bills;
  332. });
  333. controller.showTreeData();
  334. sheet.setRowCount(data.length);
  335. setUnitCombo(sheet, data);
  336. TREE_SHEET_HELPER.massOperationSheet(sheet, () => {
  337. const startRow = lockData(sheet, tree.items, false);
  338. setCells(sheet, startRow, tree.items);
  339. // 表格格式化
  340. budgetSummaryTreeSetting.cols.forEach((item, index) => {
  341. sheet.setFormatter(-1, index, item.formatter || '@', GC.Spread.Sheets.SheetArea.viewport);
  342. });
  343. });
  344. selectCell(sheet.getActiveRowIndex(), sheet.getActiveColumnIndex());
  345. }
  346. /* 右键菜单 */
  347. // 更新树结构数据
  348. const updateTree = (sheet, updateData) => {
  349. // 更新数据
  350. updateData.forEach(item => {
  351. if (item.type === 'new') {
  352. rawData.push(item.data)
  353. } else if (item.type === 'update') {
  354. const node = tree.findNode(item.data.ID);
  355. if (node) {
  356. Object.assign(node.data, item.data);
  357. }
  358. } else {
  359. const removeIndex = rawData.findIndex(d => d.ID === item.data.ID);
  360. if (removeIndex > -1) {
  361. rawData.splice(removeIndex, 1);
  362. }
  363. }
  364. });
  365. // 重新初始化树
  366. initTree(rawData, sheet, budgetSummaryTreeSetting);
  367. }
  368. let loading = false;
  369. // 插入
  370. const insert = async (sheet, selected) => {
  371. try {
  372. if (loading) {
  373. return;
  374. }
  375. loading = true;
  376. $.bootstrapLoading.start();
  377. const updateData = tree.getInsertData(selected.data.ParentID, selected.data.NextSiblingID, uuid.v1());
  378. const newData = updateData.filter(item => item.type === 'new');
  379. newData.forEach(item => {
  380. item.data.fees = [];
  381. item.data.flags = [];
  382. item.feesIndex = {};
  383. item.flagsIndex = {};
  384. item.data.type = selected.data.type;
  385. item.data.projectID = projectObj.project.property.rootProjectID;
  386. });
  387. await bulkOperation(updateData);
  388. updateTree(sheet, updateData);
  389. selectCell(sheet.getActiveRowIndex() + selected.posterityCount() + 1, sheet.getActiveColumnIndex(), true);
  390. } catch (err) {
  391. alert(err);
  392. } finally {
  393. $.bootstrapLoading.end();
  394. loading = false;
  395. }
  396. }
  397. // 删除
  398. const remove = async (sheet, selected) => {
  399. try {
  400. if (loading) {
  401. return;
  402. }
  403. loading = true;
  404. $.bootstrapLoading.start();
  405. const updateData = tree.getDeleteData(selected);
  406. await bulkOperation(updateData);
  407. updateTree(sheet, updateData);
  408. } catch (err) {
  409. alert(err);
  410. } finally {
  411. $.bootstrapLoading.end();
  412. loading = false;
  413. }
  414. }
  415. // 升级
  416. const upLevel = async (selected) => {
  417. if (!spread || !tree) {
  418. return;
  419. }
  420. const sheet = spread.getSheet(0);
  421. selected = selected ? selected : tree.selected;
  422. try {
  423. if (loading || upLevelDisabled) {
  424. return;
  425. }
  426. loading = true;
  427. $.bootstrapLoading.start();
  428. const updateData = selected.getUpLevelData();
  429. await bulkOperation(updateData);
  430. updateTree(sheet, updateData);
  431. } catch (err) {
  432. alert(err);
  433. } finally {
  434. $.bootstrapLoading.end();
  435. loading = false;
  436. }
  437. }
  438. // 降级
  439. const downLevel = async (selected) => {
  440. if (!spread || !tree) {
  441. return;
  442. }
  443. const sheet = spread.getSheet(0);
  444. selected = selected ? selected : tree.selected;
  445. try {
  446. if (loading || downLevelDisabled) {
  447. return;
  448. }
  449. loading = true;
  450. $.bootstrapLoading.start();
  451. const updateData = selected.getDownLevelData();
  452. await bulkOperation(updateData);
  453. updateTree(sheet, updateData);
  454. } catch (err) {
  455. alert(err);
  456. } finally {
  457. $.bootstrapLoading.end();
  458. loading = false;
  459. }
  460. }
  461. // 上移
  462. const upMove = async (selected) => {
  463. if (!spread || !tree) {
  464. return;
  465. }
  466. const sheet = spread.getSheet(0);
  467. selected = selected ? selected : tree.selected;
  468. try {
  469. if (loading || upMoveDisabled) {
  470. return;
  471. }
  472. loading = true;
  473. $.bootstrapLoading.start();
  474. const updateData = selected.getUpMoveData();
  475. await bulkOperation(updateData);
  476. updateTree(sheet, updateData);
  477. const prev = selected.preSibling;
  478. const row = sheet.getActiveRowIndex() - prev.posterityCount() - 1;
  479. selectCell(row, sheet.getActiveColumnIndex(), true);
  480. sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
  481. } catch (err) {
  482. alert(err);
  483. } finally {
  484. $.bootstrapLoading.end();
  485. loading = false;
  486. }
  487. }
  488. // 下移
  489. const downMove = async (selected) => {
  490. if (!spread || !tree) {
  491. return;
  492. }
  493. const sheet = spread.getSheet(0);
  494. selected = selected ? selected : tree.selected;
  495. try {
  496. if (loading || downMoveDisabled) {
  497. return;
  498. }
  499. loading = true;
  500. $.bootstrapLoading.start();
  501. const updateData = selected.getDownMoveData();
  502. await bulkOperation(updateData);
  503. updateTree(sheet, updateData);
  504. const next = selected.nextSibling;
  505. const row = sheet.getActiveRowIndex() + next.posterityCount() + 1;
  506. selectCell(row, sheet.getActiveColumnIndex(), true);
  507. sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
  508. } catch (err) {
  509. alert(err);
  510. } finally {
  511. $.bootstrapLoading.end();
  512. loading = false;
  513. }
  514. }
  515. // 初始化右键菜单
  516. const initContextMenu = () => {
  517. if (!spread) {
  518. return;
  519. }
  520. let curRow;
  521. let curNode;
  522. const sheet = spread.getSheet(0);
  523. $.contextMenu({
  524. selector: '#budget-summary-sheet',
  525. build: function ($trigger, e) {
  526. const target = SheetDataHelper.safeRightClickSelection($trigger, e, spread);
  527. curRow = target.row;
  528. curNode = tree && tree.items[curRow] || null;
  529. selectCell(target.row, target.col, true);
  530. return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
  531. },
  532. items: {
  533. insert: {
  534. name: '插入行',
  535. icon: 'fa-sign-in',
  536. disabled() {
  537. return !curNode || (curNode.data.area === BudgetArea.CONSTRUCTION_FEE && curNode.getFlag() !== fixedFlag.CONSTRUCTION_FEE);
  538. },
  539. callback() {
  540. insert(sheet, curNode);
  541. }
  542. },
  543. remove: {
  544. name: '删除行',
  545. icon: 'fa-remove',
  546. disabled() {
  547. return !curNode || isConstructionFeeArea(curNode) || curNode.getFlag();
  548. },
  549. callback() {
  550. remove(sheet, curNode);
  551. }
  552. },
  553. /* upLevel: {
  554. name: '升级',
  555. icon: 'fa-arrow-left',
  556. disabled() {
  557. return !curNode || !curNode.canUpLevel() || isConstructionFeeArea(curNode);
  558. },
  559. callback() {
  560. upLevel(sheet, curNode);
  561. }
  562. },
  563. downLevel: {
  564. name: '降级',
  565. icon: 'fa-arrow-right',
  566. disabled() {
  567. return !curNode || !curNode.canDownLevel() || isConstructionFeeArea(curNode) || isConstructionFeeArea(curNode.preSibling);
  568. },
  569. callback() {
  570. downLevel(sheet, curNode);
  571. }
  572. },
  573. upMove: {
  574. name: '上移',
  575. icon: 'fa-arrow-up',
  576. disabled() {
  577. return !curNode || !curNode.canUpMove() || isConstructionFeeArea(curNode) || isConstructionFeeArea(curNode.preSibling);
  578. },
  579. callback() {
  580. upMove(sheet, curNode);
  581. }
  582. },
  583. downMove: {
  584. name: '下移',
  585. icon: 'fa-arrow-down',
  586. disabled() {
  587. return !curNode || !curNode.canDownMove() || isConstructionFeeArea(curNode) || isConstructionFeeArea(curNode.nextSibling);
  588. },
  589. callback() {
  590. downMove(sheet, curNode);
  591. }
  592. }, */
  593. refresh: {
  594. name: '刷新数据',
  595. icon: 'fa-refresh',
  596. callback() {
  597. init(projectObj.project.property.rootProjectID);
  598. }
  599. },
  600. }
  601. });
  602. }
  603. // 初始化
  604. const init = async (constructionID) => {
  605. try {
  606. $.bootstrapLoading.start();
  607. const { treeData, costGrowthRate, growthPeriod } = await ajaxPost('/bills/initialBudgetSummary', { constructionID });
  608. calcSetting.costGrowthRate = costGrowthRate;
  609. calcSetting.growthPeriod = growthPeriod;
  610. $('#costGrowthRate').val(costGrowthRate);
  611. $('#growthPeriod').val(growthPeriod);
  612. rawData = treeData;
  613. rawData.forEach((item) => {
  614. if (item.quantity) {
  615. item.quantity = parseFloat(item.quantity);
  616. }
  617. item.feesIndex = getFeeIndex(item.fees);
  618. item.flagsIndex = {};
  619. if (item.flags) {
  620. item.flags.forEach((flag) => {
  621. item.flagsIndex[flag.fieldName] = flag;
  622. });
  623. }
  624. });
  625. const spread = initSpread();
  626. const sheet = spread.getSheet(0);
  627. initTree(rawData, sheet, budgetSummaryTreeSetting);
  628. calcBase.initBudget();
  629. } catch (err) {
  630. console.log(err);
  631. alert(err);
  632. } finally {
  633. $.bootstrapLoading.end();
  634. }
  635. }
  636. // 点击tab,重新初始化
  637. $('#tab-budget-summary').click(function () {
  638. if (!$(this).hasClass('active')) {
  639. init(projectObj.project.property.rootProjectID);
  640. }
  641. });
  642. $('#budget-upLevel').click(() => {
  643. upLevel();
  644. });
  645. $('#budget-downLevel').click(() => {
  646. downLevel();
  647. });
  648. $('#budget-upMove').click(() => {
  649. upMove();
  650. });
  651. $('#budget-downMove').click(() => {
  652. downMove();
  653. });
  654. /* 建设项目设置 */
  655. $('#openConstructionSet').click(() => {
  656. $('#constructionSet').modal('show');
  657. });
  658. function isKeyNumber(keyCode) {
  659. // 数字
  660. if (keyCode >= 48 && keyCode <= 57) {
  661. return true;
  662. } else if (keyCode >= 96 && keyCode <= 105) { //小键盘数字
  663. return true;
  664. } else if (keyCode == 8 || keyCode == 46 || keyCode == 37 || keyCode == 39 || keyCode == 108 || keyCode == 110) { // Backspace, del, 左右方向键
  665. return true;
  666. } else if (keyCode >= 112 && keyCode <= 123) { //F1 -F12
  667. return true;
  668. }
  669. return false;
  670. }
  671. //年造价增涨率
  672. $('#costGrowthRate').keydown(function (e) {
  673. return isKeyNumber(e.keyCode);
  674. });
  675. //计费年限
  676. $("#growthPeriod").keydown(function (e) {
  677. return isKeyNumber(e.keyCode);
  678. });
  679. // 确认设置
  680. $('#construction-set-ok').click(async () => {
  681. try {
  682. $.bootstrapLoading.start();
  683. const curCostGrowthRate = $('#costGrowthRate').val();
  684. const curGrowthPeriod = $('#growthPeriod').val();
  685. const bulkData = [
  686. {
  687. type: 'updateProject',
  688. data: {
  689. ID: projectObj.project.property.rootProjectID,
  690. 'property.costGrowthRate': curCostGrowthRate,
  691. 'property.growthPeriod': curGrowthPeriod,
  692. }
  693. }
  694. ];
  695. await bulkOperation(bulkData);
  696. calcSetting.costGrowthRate = curCostGrowthRate;
  697. calcSetting.growthPeriod = curGrowthPeriod;
  698. } catch (err) {
  699. alert(err);
  700. $('#costGrowthRate').val(calcSetting.costGrowthRate);
  701. $('#growthPeriod').val(calcSetting.growthPeriod);
  702. } finally {
  703. $.bootstrapLoading.end();
  704. }
  705. });
  706. // 对外暴露
  707. return {
  708. getTree: () => tree,
  709. getSheet: () => spread.getSheet(0),
  710. calcSetting,
  711. edit,
  712. };
  713. })();