schedule_plan.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /**
  2. * 进度台账相关js
  3. *
  4. * @author Ellisran
  5. * @date 2020/11/6
  6. * @version
  7. */
  8. function getTenderId() {
  9. return window.location.pathname.split('/')[2];
  10. }
  11. $(function () {
  12. autoFlashHeight();
  13. if(schedule && !schedule.mode) {
  14. $('#mode').modal('show');
  15. }
  16. // 初始化台账
  17. const ledgerSpread = SpreadJsObj.createNewSpread($('#ledger-spread')[0]);
  18. const treeSetting = {
  19. id: 'ledger_id',
  20. pid: 'ledger_pid',
  21. order: 'order',
  22. level: 'level',
  23. rootId: -1,
  24. fullPath: 'full_path',
  25. //treeCacheKey: 'ledger_bills_fold' + '_' + getTenderId(),
  26. // markFoldKey: 'bills-fold',
  27. // markFoldSubKey: window.location.pathname.split('/')[2],
  28. };
  29. const static_cols = [
  30. {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
  31. {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true},
  32. {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
  33. {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
  34. {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
  35. {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
  36. ];
  37. const ledgerSpreadSetting = {
  38. emptyRows: 0,
  39. headRows: 2,
  40. headRowHeight: [25, 25],
  41. defaultRowHeight: 21,
  42. headerFont: '12px 微软雅黑',
  43. font: '12px 微软雅黑',
  44. // readOnly: true,
  45. localCache: {
  46. key: 'ledger-bills',
  47. colWidth: true,
  48. }
  49. };
  50. const monthsCols = [];
  51. const calcCols = ['total_price'];
  52. if(scheduleMonth.length > 0) {
  53. for (const sm of scheduleMonth) {
  54. const readOnly = sm.stage_used !== 0;
  55. const yearmonth = sm.yearmonth.split('-')[0] + '年' + parseInt(sm.yearmonth.split('-')[1]) + '月';
  56. const cols = {title: yearmonth + '|计划工程量', colSpan: '2|1', rowSpan: '1|1', field: sm.yearmonth+'_gcl', hAlign: 2, width: 90, type: 'Number', readOnly: readOnly ? readOnly : 'readOnly.gcl'};
  57. const cols2 = {title: '|计划金额(万元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_tp', hAlign: 2, width: 90, type: 'Number', readOnly: readOnly ? readOnly : 'readOnly.tp'};
  58. monthsCols.push(cols);
  59. monthsCols.push(cols2);
  60. calcCols.push(sm.yearmonth+'_gcl');
  61. calcCols.push(sm.yearmonth+'_tp');
  62. }
  63. }
  64. treeSetting.calcFields = calcCols;
  65. const ledgerTree = createNewPathTree('filter', treeSetting);
  66. const spreadHeaderCols = static_cols.concat(monthsCols);
  67. ledgerSpreadSetting.cols = spreadHeaderCols;
  68. const ledgerCol = {
  69. readOnly: {
  70. tp: function (data) {
  71. let flag = data.is_leaf;
  72. if (data.is_leaf) {
  73. flag = schedule && schedule.mode === mode.tp;
  74. }
  75. return !flag;
  76. },
  77. gcl: function (data) {
  78. let flag = data.is_leaf;
  79. if (data.is_leaf) {
  80. flag = schedule && schedule.mode === mode.gcl;
  81. }
  82. return !flag;
  83. },
  84. },
  85. };
  86. sjsSettingObj.setFxTreeStyle(ledgerSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
  87. if (thousandth) sjsSettingObj.setTpThousandthFormat(ledgerSpreadSetting);
  88. SpreadJsObj.initSpreadSettingEvents(ledgerSpreadSetting, ledgerCol);
  89. SpreadJsObj.initSheet(ledgerSpread.getActiveSheet(), ledgerSpreadSetting);
  90. SpreadJsObj.selChangedRefreshBackColor(ledgerSpread.getActiveSheet());
  91. postData('/tender/' + getTenderId() + '/schedule/ledger/load', {}, function (data) {
  92. // let treeData = [];
  93. // for(const sl of selectedLedgerList) {
  94. // const one = _.find(data, { 'ledger_id' : sl });
  95. // treeData.push(one);
  96. // }
  97. // treeData = setLeafData(treeData);
  98. // console.log(treeData);
  99. // let treeData = data;
  100. const calcList = ['total_price'];
  101. const showList = ['ledger_id', 'ledger_pid', 'order', 'level', 'tender_id', 'full_path',
  102. 'code', 'name', 'unit', 'dgn_qty1', 'dgn_qty2', 'dgn_price', 'quantity', 'total_price'];
  103. for (const m of monthList) {
  104. showList.push(m + '_tp');
  105. showList.push(m + '_gcl');
  106. // calcList.push(m + '_tp');
  107. // calcList.push(m + '_gcl');
  108. }
  109. const baseLedgerTree = createNewPathTree('base', {
  110. id: 'ledger_id',
  111. pid: 'ledger_pid',
  112. order: 'order',
  113. level: 'level',
  114. rootId: -1,
  115. fullPath: 'full_path',
  116. calcFields: calcList,
  117. calcFun: function (node) {
  118. node.dgn_price = ZhCalc.round(ZhCalc.div(node.total_price, node.dgn_qty1), 2);
  119. }
  120. });
  121. const newLedgerList = setMonthToLedger(data.bills, data.slm);
  122. baseLedgerTree.loadDatas(newLedgerList);
  123. treeCalc.calculateAll(baseLedgerTree);
  124. console.log(baseLedgerTree);
  125. for (const d of baseLedgerTree.nodes) {
  126. if (!d.b_code) {
  127. const one = _.find(selectedLedgerList, function (item) {
  128. return item === d.ledger_id;
  129. });
  130. if(one) {
  131. ledgerTree.addData(d, showList);
  132. }
  133. }
  134. }
  135. console.log(ledgerTree);
  136. ledgerTree.sortTreeNode(true);
  137. treeCalc.calculateAll(ledgerTree);
  138. // console.log(ledgerTree);
  139. SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
  140. }, null, true);
  141. const ledgerSpreadObj = {
  142. refreshTree: function (sheet, data) {
  143. SpreadJsObj.massOperationSheet(sheet, function () {
  144. const tree = sheet.zh_tree;
  145. // 处理删除
  146. if (data.delete) {
  147. data.delete.sort(function (x, y) {
  148. return y.deleteIndex - x.deleteIndex;
  149. });
  150. for (const d of data.delete) {
  151. sheet.deleteRows(d.deleteIndex, 1);
  152. }
  153. }
  154. // 处理新增
  155. if (data.create) {
  156. const newNodes = data.create;
  157. if (newNodes) {
  158. newNodes.sort(function (a, b) {
  159. return a.index - b.index;
  160. });
  161. for (const node of newNodes) {
  162. sheet.addRows(node.index, 1);
  163. SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(node), 1);
  164. }
  165. }
  166. }
  167. // 处理更新
  168. if (data.update) {
  169. const rows = [];
  170. for (const u of data.update) {
  171. rows.push(tree.nodes.indexOf(u));
  172. }
  173. SpreadJsObj.reLoadRowsData(sheet, rows);
  174. }
  175. // 处理展开
  176. if (data.expand) {
  177. const expanded = [];
  178. for (const e of data.expand) {
  179. if (expanded.indexOf(e) === -1) {
  180. const posterity = tree.getPosterity(e);
  181. for (const p of posterity) {
  182. sheet.setRowVisible(tree.nodes.indexOf(p), p.visible);
  183. expanded.push(p);
  184. }
  185. }
  186. }
  187. }
  188. });
  189. },
  190. editEnded: function (e, info) {
  191. if (info.sheet.zh_setting) {
  192. const select = SpreadJsObj.getSelectObject(info.sheet);
  193. const col = info.sheet.zh_setting.cols[info.col];
  194. const validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : null);
  195. const orgValue = select[col.field];
  196. if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
  197. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  198. return;
  199. }
  200. if (isNaN(validText)) {
  201. toastr.error('不能输入其它非数字类型字符');
  202. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  203. return;
  204. }
  205. const yearmonth = col.field.split('_')[0];
  206. const mode = col.field.split('_')[1];
  207. let plan_gcl = 0;
  208. let plan_tp = 0;
  209. // 判断输入位数,提示
  210. if (mode === 'tp') {
  211. const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.tp) +'})?$');
  212. if (validText !== null && (!reg.test(validText))) {
  213. toastr.error('输入金额小数位数不能大于' + tenderInfo.decimal.tp + '位');
  214. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  215. return;
  216. }
  217. plan_gcl = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.div(validText, select.dgn_price), tenderInfo.decimal.up) : 0;
  218. plan_tp = validText;
  219. } else {
  220. const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.up) +'})?$');
  221. if (validText !== null && (!reg.test(validText))) {
  222. toastr.error('输入工程量小数位数不能大于' + tenderInfo.decimal.up + '位');
  223. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  224. return;
  225. }
  226. plan_gcl = validText;
  227. plan_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), tenderInfo.decimal.tp) : 0;
  228. }
  229. select[col.field] = validText;
  230. const updateData = {
  231. lid: select.ledger_id,
  232. yearmonth,
  233. plan_gcl,
  234. plan_tp,
  235. };
  236. console.log(updateData);
  237. postData(window.location.pathname + '/save', {type: 'ledger_edit', postData: updateData}, function (result) {
  238. if (mode === 'tp') {
  239. select[yearmonth + '_gcl'] = plan_gcl;
  240. } else {
  241. select[yearmonth + '_tp'] = plan_tp;
  242. }
  243. const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
  244. SpreadJsObj.reLoadNodesData(info.sheet, nodes);
  245. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  246. },function () {
  247. select[col.field] = orgValue;
  248. const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
  249. SpreadJsObj.reLoadNodesData(info.sheet, nodes);
  250. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  251. })
  252. }
  253. },
  254. deletePress: function (sheet) {
  255. return;
  256. },
  257. clipboardPasted(e, info) {
  258. const hint = {
  259. cellError: {type: 'error', msg: '粘贴内容超出了表格范围'},
  260. numberExpr: {type: 'error', msg: '不能粘贴其它非数字类型字符'},
  261. };
  262. const range = info.cellRange;
  263. if (range.rowCount > 1 || range.colCount > 1) {
  264. toastMessageUniq(hint.cellError);
  265. SpreadJsObj.reLoadSheetHeader(ledgerSpread.getActiveSheet());
  266. SpreadJsObj.reLoadSheetData(ledgerSpread.getActiveSheet());
  267. return;
  268. }
  269. const select = SpreadJsObj.getSelectObject(info.sheet);
  270. const col = info.sheet.zh_setting.cols[range.col];
  271. const validText = is_numeric(info.pasteData.text) ? parseFloat(info.pasteData.text) : (info.pasteData.text ? trimInvalidChar(info.pasteData.text) : null);
  272. const orgValue = select[col.field];
  273. if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
  274. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  275. return;
  276. }
  277. if (isNaN(validText)) {
  278. toastr.error('不能粘贴其它非数字类型字符');
  279. SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
  280. return;
  281. }
  282. const yearmonth = col.field.split('_')[0];
  283. const mode = col.field.split('_')[1];
  284. let plan_gcl = 0;
  285. let plan_tp = 0;
  286. // 判断输入位数,提示
  287. if (mode === 'tp') {
  288. const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.tp) +'})?$');
  289. if (validText !== null && (!reg.test(validText))) {
  290. toastr.error('粘贴的金额小数位数不能大于' + tenderInfo.decimal.tp + '位');
  291. SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
  292. return;
  293. }
  294. plan_gcl = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.div(validText, select.dgn_price), tenderInfo.decimal.up) : 0;
  295. plan_tp = validText;
  296. } else {
  297. const reg = new RegExp('^([-]?)\\d+(\\.\\d{0,'+ parseInt(tenderInfo.decimal.up) +'})?$');
  298. if (validText !== null && (!reg.test(validText))) {
  299. toastr.error('粘贴的工程量小数位数不能大于' + tenderInfo.decimal.up + '位');
  300. SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
  301. return;
  302. }
  303. plan_gcl = validText;
  304. plan_tp = select.dgn_price && select.dgn_price !== 0 ? ZhCalc.round(ZhCalc.mul(validText, select.dgn_price), tenderInfo.decimal.tp) : 0;
  305. }
  306. select[col.field] = validText;
  307. const updateData = {
  308. lid: select.ledger_id,
  309. yearmonth,
  310. plan_gcl,
  311. plan_tp,
  312. };
  313. postData(window.location.pathname + '/save', {type: 'ledger_edit', postData: updateData}, function (result) {
  314. if (mode === 'tp') {
  315. select[yearmonth + '_gcl'] = plan_gcl;
  316. } else {
  317. select[yearmonth + '_tp'] = plan_tp;
  318. }
  319. const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
  320. SpreadJsObj.reLoadNodesData(info.sheet, nodes);
  321. SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
  322. },function () {
  323. select[col.field] = orgValue;
  324. const nodes = treeCalc.calculateParent(info.sheet.zh_tree, select);
  325. SpreadJsObj.reLoadNodesData(info.sheet, nodes);
  326. SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
  327. })
  328. },
  329. };
  330. ledgerSpread.bind(spreadNS.Events.EditEnded, ledgerSpreadObj.editEnded);
  331. SpreadJsObj.addDeleteBind(ledgerSpread, ledgerSpreadObj.deletePress);
  332. ledgerSpread.bind(spreadNS.Events.ClipboardPasted, ledgerSpreadObj.clipboardPasted);
  333. // 进度计算方式选择
  334. $('.mode-select').on('click', function () {
  335. const _self = $(this);
  336. postData(window.location.pathname + '/save', {type: 'mode', postData: $(this).data('mode')}, function (result) {
  337. _self.addClass('disabled').attr('disabled', true);
  338. _self.parents('.col-6').siblings('.col-6').find('button').removeClass('disabled').removeAttr('disabled');
  339. $('#mode-tips').show();
  340. $('#mode-cancel').show();
  341. $('#mode').modal('hide');
  342. schedule.mode = _self.data('mode');
  343. SpreadJsObj.reLoadSheetData(ledgerSpread.getActiveSheet());
  344. })
  345. });
  346. // 月份添加
  347. $('#add-month').click(function () {
  348. const range = $('#month-range').val();
  349. if(range === '') {
  350. toastr.error('请选择计划周期时间');
  351. return;
  352. }
  353. const addMonthList = [];
  354. const cycle = range.split(' ~ ');
  355. if(cycle.length === 1) {
  356. addMonthList.push(cycle[0]);
  357. } else {
  358. // 多个月份
  359. const back_year = parseInt(cycle[1].split('-')[0]);
  360. const back_month = parseInt(cycle[1].split('-')[1]);
  361. const front_year = parseInt(cycle[0].split('-')[0]);
  362. const front_month = parseInt(cycle[0].split('-')[1]);
  363. if(back_year > front_year) {
  364. const num = getDistanceMonth(cycle[0], cycle[1]);
  365. let j = 1;
  366. for (let i = 0; i <= num; i++) {
  367. if(front_month + i > 12*j) {
  368. j = j + 1;
  369. }
  370. const m = (front_month + i)%12 === 0 ? 12 : (front_month + i)%12;
  371. addMonthList.push((front_year + (j-1)) + '-' + (m < 10 ? '0' + m : m));
  372. }
  373. } else if (back_year === front_year) {
  374. // 小于1年并没有跨年
  375. for (let i = front_month; i <= back_month; i++) {
  376. addMonthList.push(back_year + '-' + (i < 10 ? '0' + i : i));
  377. }
  378. }
  379. }
  380. // 判断是否已添加本月份
  381. if (addMonthList.length > 0) {
  382. const hadmonth = [];
  383. for (const m of addMonthList) {
  384. const one = _.find(scheduleMonth, { yearmonth: m });
  385. console.log(one, m);
  386. if (one) {
  387. hadmonth.push(m);
  388. }
  389. }
  390. if (hadmonth.length > 0) {
  391. let html = '';
  392. for (const hm of hadmonth) {
  393. html += `<div class="alert alert-danger">${hm} 已创建</div>`;
  394. }
  395. $('#add-month-error-list').html(html);
  396. $('#add-month-error-list').show();
  397. return;
  398. }
  399. } else {
  400. toastr.error('请选择计划周期时间');
  401. return;
  402. }
  403. $('#add-month-error-list').html('');
  404. $('#add-month-error-list').hide();
  405. const _self = $(this);
  406. postData(window.location.pathname + '/save', {type: 'addmonth', postData: addMonthList}, function (result) {
  407. _self.addClass('disabled').attr('disabled', true);
  408. toastr.success('新增成功');
  409. setTimeout(function () {
  410. window.location.reload();
  411. }, 500)
  412. })
  413. });
  414. $('#month-table input[type="checkbox"]').click(function () {
  415. const selectedMonth = [];
  416. $('#month-table input:checkbox:checked').each(function () {
  417. selectedMonth.push('「' + $(this).parents('td').siblings('td').text() + '」');
  418. });
  419. if(selectedMonth.length > 0) {
  420. $('#del-month-list').text(selectedMonth.join(''));
  421. $('#del-month-list').parent().show();
  422. $('#del-month').removeAttr('disabled');
  423. } else {
  424. $('#del-month-list').parent().hide();
  425. $('#del-month').attr('disabled', true);
  426. }
  427. });
  428. $('#del-month').click(function () {
  429. const selectedMonth = [];
  430. $('#month-table input:checkbox:checked').each(function () {
  431. selectedMonth.push($(this).parents('td').siblings().text());
  432. });
  433. if (selectedMonth.length === 0) {
  434. toastr.error('请选择删除的计划周期');
  435. return;
  436. }
  437. const _self = $(this);
  438. postData(window.location.pathname + '/save', {type: 'delmonth', postData: selectedMonth}, function (result) {
  439. _self.addClass('disabled').attr('disabled', true);
  440. toastr.success('删除成功');
  441. setTimeout(function () {
  442. window.location.reload();
  443. }, 500)
  444. })
  445. });
  446. $.subMenu({
  447. menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
  448. toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
  449. key: 'menu.1.0.0',
  450. miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
  451. callback: function (info) {
  452. if (info.mini) {
  453. $('.panel-title').addClass('fluid');
  454. $('#sub-menu').removeClass('panel-sidebar');
  455. } else {
  456. $('.panel-title').removeClass('fluid');
  457. $('#sub-menu').addClass('panel-sidebar');
  458. }
  459. ledgerSpread.refresh();
  460. autoFlashHeight();
  461. }
  462. });
  463. });
  464. // 月份间隔
  465. function getDistanceMonth(startTime,endTime){
  466. startTime = new Date(startTime);
  467. endTime = new Date(endTime);
  468. var dateToMonth = 0;
  469. var startDate=startTime.getDate() + startTime.getHours()/24 + startTime.getMinutes()/24/60;
  470. var endDate=endTime.getDate() +endTime.getHours()/24 + endTime.getMinutes()/24/60;
  471. if(endDate >= startDate){
  472. dateToMonth = 0;
  473. }else{
  474. dateToMonth = -1;
  475. }
  476. let yearToMonth = (endTime.getYear() - startTime.getYear()) * 12;
  477. let monthToMonth = endTime.getMonth() - startTime.getMonth();
  478. return yearToMonth + monthToMonth + dateToMonth;
  479. }
  480. function setLeafData(tree) {
  481. const newtree = [];
  482. for (const t of tree) {
  483. const child = _.find(tree, { 'ledger_pid': t.ledger_id });
  484. if (!child && !t.is_leaf) {
  485. t.is_leaf = true;
  486. }
  487. newtree.push(t);
  488. }
  489. return newtree;
  490. }
  491. function setMonthToLedger(ledgerList, slm) {
  492. if (slm.length > 0) {
  493. for(const s of slm) {
  494. const index = _.findIndex(ledgerList, { 'ledger_id': s.lid });
  495. if (index && index !== -1) {
  496. ledgerList[index][s.yearmonth + '_tp'] = s.plan_tp;
  497. ledgerList[index][s.yearmonth + '_gcl'] = s.plan_gcl;
  498. }
  499. }
  500. }
  501. return ledgerList;
  502. }
  503. const is_numeric = (value) => {
  504. if (typeof(value) === 'object') {
  505. return false;
  506. } else {
  507. return !Number.isNaN(Number(value)) && value.toString().trim() !== '';
  508. }
  509. };