budgetSummarySheet.js 21 KB

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