phase_pay_detail.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. 'use strict';
  2. $(document).ready(() => {
  3. const payUtils = {
  4. tips: {
  5. name: function(data) {
  6. const tips = [];
  7. if (data) {
  8. if (data.pause) tips.push('当前项已停用');
  9. if (!data.is_yf) tips.push('当前项不参与本期应付计算');
  10. }
  11. return tips.join('<br/>');
  12. },
  13. range_tp: function (data) {
  14. if (!data || (!data.range_expr && !data.range_tp) || !data.dl_type) return '';
  15. if (data.dl_type === 1) {
  16. return '计提期限为(当 计量期数 ≥ ' + data.dl_count + ')';
  17. } else if (data.dl_type === 2) {
  18. switch (data.dl_tp_type) {
  19. case 'contract':
  20. return '计提期限为(累计合同计量 ≥ ' + data.dl_tp + ')';
  21. case 'qc':
  22. return '计提期限为(累计变更计量 ≥ ' + data.dl_tp + ')';
  23. case 'gather':
  24. return '计提期限为(累计完成计量 ≥ ' + data.dl_tp + ')';
  25. }
  26. }
  27. }
  28. },
  29. check: {
  30. isFixed: function(data) {
  31. return data.is_fixed;
  32. },
  33. isStarted: function (data) {
  34. return data.pre_used;
  35. },
  36. isYf: function(data) {
  37. return data.pay_type === 'bqyf';
  38. },
  39. isSf: function(data) {
  40. return data.pay_type === 'bqsf';
  41. }
  42. }
  43. };
  44. const payCalc = (function (b, a) {
  45. class PayCalc {
  46. constructor (bases, add) {
  47. this.percentReg = /((\d+)|((\d+)(\.\d+)))%/g;
  48. this.bases = bases;
  49. this.bases.sort(function (a, b) {
  50. return a.sort - b.sort;
  51. });
  52. for (const b of this.bases) {
  53. b.reg = new RegExp(b.code, 'igm');
  54. }
  55. this.addBase = add;
  56. this.orderReg = /f\d+/ig;
  57. this.nodeReg = /<<[a-z0-9\-]+>>/ig;
  58. }
  59. trans2OrderExpr(expr, payTree) {
  60. const nodeParam = expr.match(this.nodeReg);
  61. if (nodeParam) {
  62. for (const op of nodeParam) {
  63. const id = op.substring(2, op.length - 2);
  64. const payNode = payTree.nodes.find(x => { return x.uuid === id; });
  65. expr = expr.replace(op, payNode ? `f${payTree.getNodeIndex(payNode) + 1}` || '' : 0);
  66. }
  67. }
  68. return expr;
  69. }
  70. trans2NodeExpr(expr, payTree) {
  71. const orderParam = expr.match(this.orderReg);
  72. if (orderParam) {
  73. for (const op of orderParam) {
  74. const order = parseInt(op.substring(1, op.length));
  75. const payNode = payTree.nodes[order - 1];
  76. expr = expr.replace(op, payNode ? `<<${payNode.uuid}>>` || '' : 0);
  77. }
  78. }
  79. return expr;
  80. }
  81. checkExprValid(expr, invalidParam, selfId, payTree) {
  82. if (!expr) return [true, ''];
  83. const param = [];
  84. let num = '', base = '';
  85. let fixedIdParam;
  86. for (let i = 0, iLen = expr.length; i < iLen; i++) {
  87. const subExpr = expr.substring(i, expr.length);
  88. if (/^[\d\.%]+/.test(expr[i])) {
  89. if (base !== '') {
  90. param.push({type: 'base', value: base});
  91. base = '';
  92. }
  93. num = num + expr[i];
  94. } else if (this.nodeReg.test(subExpr)) {
  95. if (num !== '') {
  96. param.push({type: 'num', value: num});
  97. num = '';
  98. }
  99. if (base !== '') {
  100. param.push({type: 'base', value: base});
  101. base = '';
  102. }
  103. // const node = this.nodeReg.exec(subExpr);
  104. const node = subExpr.match(this.nodeReg);
  105. param.push({type: 'node', value: node[0]});
  106. i = i + node[0].length - 1;
  107. } else if (/^[a-z]/.test(expr[i])) {
  108. if (num !== '') {
  109. param.push({type: 'num', value: num});
  110. num = '';
  111. }
  112. base = base + expr[i];
  113. } else if (expr[i] === '(') {
  114. if (num !== '') {
  115. param.push({type: 'num', value: num});
  116. num = '';
  117. }
  118. if (base !== '') {
  119. param.push({type: 'base', value: base});
  120. base = '';
  121. }
  122. param.push({type: 'left', value: '('});
  123. } else if (expr[i] === ')') {
  124. if (num !== '') {
  125. param.push({type: 'num', value: num});
  126. num = '';
  127. }
  128. if (base !== '') {
  129. param.push({type: 'base', value: base});
  130. base = '';
  131. }
  132. param.push({type: 'right', value: ')'});
  133. } else if (/^[\+\-*\/]/.test(expr[i])) {
  134. if (num !== '') {
  135. param.push({type: 'num', value: num});
  136. num = '';
  137. }
  138. if (base !== '') {
  139. param.push({type: 'base', value: base});
  140. base = '';
  141. }
  142. param.push({type: 'calc', value: expr[i]});
  143. } else {
  144. return [false, '输入的表达式含有非法字符: ' + expr[i]];
  145. }
  146. }
  147. if (num !== '') {
  148. param.push({type: 'num', value: num});
  149. num = '';
  150. }
  151. if (base !== '') {
  152. param.push({type: 'base', value: base});
  153. base = '';
  154. }
  155. if (param.length === 0) return [true, ''];
  156. if (param.length > 1) {
  157. if (param[0].value === '-' && param[1].type === 'num') {
  158. param[1].value = '-' + param[1].value;
  159. param.shift();
  160. }
  161. }
  162. const iLen = param.length;
  163. let iLeftCount = 0, iRightCount = 0;
  164. for (const [i, p] of param.entries()) {
  165. if (p.type === 'calc') {
  166. if (i === 0 || i === iLen - 1)
  167. return [false, '输入的表达式非法:计算符号' + p.value + '前后应有数字或计算基数'];
  168. }
  169. if (p.type === 'num') {
  170. num = p.value.replace('%', '');
  171. if (p.value.length - num.length > 1)
  172. return [false, '输入的表达式非法:' + p.value + '不是一个有效的数字'];
  173. num = _.toNumber(num);
  174. if (num === undefined || num === null || _.isNaN(num))
  175. return [false, '输入的表达式非法:' + p.value + '不是一个有效的数字'];
  176. if (i > 0) {
  177. if (param[i - 1].type !== 'calc' && param[i - 1].type !== 'left') {
  178. return [false, '输入的表达式非法:' + p.value + '前应有运算符'];
  179. } else if (param[i - 1].value === '/' && num === 0) {
  180. return [false, '输入的表达式非法:请勿除0'];
  181. }
  182. }
  183. }
  184. if (p.type === 'base') {
  185. const baseParam = _.find(calcBase, {code: p.value});
  186. if (!baseParam)
  187. return [false, '输入的表达式非法:不存在计算基数' + p.value];
  188. if (invalidParam && invalidParam.indexOf(p.value) >= 0)
  189. return [false, '不可使用计算基数' + p.value];
  190. if (i > 0 && (param[i - 1].type === 'num' || param[i - 1].type === 'right'))
  191. return [false, '输入的表达式非法:' + p.value + '前应有运算符'];
  192. }
  193. if (p.type === 'node') {
  194. if (!selfId) return [false, '输入的表达式错误:不支持行号引用'];
  195. if ([`<<${selfId}>>`].indexOf(p.value) >= 0) return [false, '输入的表达式非法:请勿引用自己'];
  196. if (!fixedIdParam) {
  197. fixedIdParam = payTree.nodes.filter(x => { return x.is_fixed; }).map(x => { return `<<${x.uuid}>>`});
  198. }
  199. if (fixedIdParam.indexOf(p.value) >= 0) return [false, '输入的表达式非法:请勿引用固定项'];
  200. }
  201. if (p.type === 'left') {
  202. iLeftCount += 1;
  203. if (i !== 0 && param[i-1].type !== 'calc')
  204. return [false, '输入的表达式非法:(前应有运算符'];
  205. }
  206. if (p.type === 'right') {
  207. iRightCount += 1;
  208. if (i !== iLen - 1 && param[i+1].type !== 'calc')
  209. return [false, '输入的表达式非法:)后应有运算符'];
  210. if (iRightCount > iLeftCount)
  211. return [false, '输入的表达式非法:")"前无对应的"("'];
  212. }
  213. }
  214. if (iLeftCount > iRightCount)
  215. return [false, '输入的表达式非法:"("后无对应的")"'];
  216. if (selfId) {
  217. const circular = payCalc.checkCircularExpr(expr, selfId, payTree);
  218. // 当前循环计算不检查父项
  219. if (circular) return [false, '输入的表达式非法:循环引用'];
  220. }
  221. return [true, ''];
  222. }
  223. checkSfExpr(text, data, payNode, payTree) {
  224. if (text) {
  225. const num = _.toNumber(text);
  226. if (num) {
  227. data.expr = num;
  228. } else {
  229. const expr = this.trans2NodeExpr($.trim(text).replace('\t', '').replace('=', '').toLowerCase(), payTree);
  230. const [valid, msg] = this.checkExprValid(expr, [], payNode.uuid, payTree);
  231. if (!valid) return [valid, msg];
  232. data.expr = expr;
  233. }
  234. } else {
  235. data.tp = 0;
  236. data.expr = '';
  237. }
  238. return [true, ''];
  239. }
  240. checkExpr(text, data, payNode, payTree) {
  241. if (text) {
  242. const num = _.toNumber(text);
  243. if (num) {
  244. data.tp = num;
  245. data.expr = '';
  246. } else {
  247. const expr = this.trans2NodeExpr($.trim(text).replace('\t', '').replace('=', '').toLowerCase(), payTree);
  248. const [valid, msg] = this.checkExprValid(expr, ['bqyf'], payNode.uuid, payTree);
  249. if (!valid) return [valid, msg];
  250. data.expr = expr;
  251. data.tp = 0;
  252. }
  253. } else {
  254. data.tp = 0;
  255. data.expr = '';
  256. }
  257. return [true, ''];
  258. }
  259. checkRangeExpr(payNode, text, data) {
  260. if (!payNode) return [false, '数据错误'];
  261. const num = text ? _.toNumber(text) : 0;
  262. let expr = text ? (num ? '' : text) : '';
  263. expr = expr ? $.trim(expr).replace('\t', '').replace('=', '').toLowerCase() : '';
  264. const [valid, msg] = this.checkExprValid(expr, ['bqwc', 'ybbqwc', 'bqht', 'bqbg', 'bqyf']);
  265. if (!valid) return [valid, msg];
  266. if (payUtils.check.isStarted(payNode)) {
  267. if (payUtils.check.isSf(payNode)) {
  268. const value = expr ? payCalc.calculateExpr(expr) : num;
  269. if (payNode.pre_tp && value < payNode.pre_tp) return [false, '截止上期已计量' + payNode.pre_tp + ',扣款限额请勿少于改值'];
  270. data.range_tp = num;
  271. data.range_expr = expr;
  272. return [true, ''];
  273. } else {
  274. // if (payNode.pre_finish) return [false, '已达扣款限额,请勿修改'];
  275. // const value = expr ? payCalc.calculateExpr(expr) : num;
  276. // if (payNode.pre_tp && value < payNode.pre_tp) return [false, '截止上期已计量' + payNode.pre_tp + ',扣款限额请勿少于改值'];
  277. // data.rprice = num;
  278. // data.rexpr = expr;
  279. return [false, '已经开始使用,请勿修改扣款限额'];
  280. }
  281. } else {
  282. data.range_tp = num;
  283. data.range_expr = expr;
  284. return [true, ''];
  285. }
  286. }
  287. checkStartExpr(payNode, text, data) {
  288. if (!payNode) return [false, '数据错误'];
  289. const num = text ? _.toNumber(text) : 0;
  290. let expr = text ? (num ? '' : text) : '';
  291. expr = expr ? $.trim(expr).replace('\t', '').replace('=', '').toLowerCase() : '';
  292. const [valid, msg] = this.checkExprValid(expr, ['bqwc', 'ybbqwc', 'bqht', 'bqbg', 'bqyf']);
  293. if (!valid) return [valid, msg];
  294. if (payUtils.check.isStarted(payNode)) {
  295. return [false, '已经开始计量,请勿修改起扣金额'];
  296. } else {
  297. if (this.addBase.pre_gather_tp) {
  298. const value = expr ? payCalc.calculateExpr(expr) : num;
  299. if (this.addBase.pre_gather_tp && value < this.addBase.pre_gather_tp)
  300. return [false, '起扣金额请勿少于本期完成截止上期计量金额' + this.addBase.pre_gather_tp];
  301. data.start_tp = num;
  302. data.start_expr = expr;
  303. return [true, ''];
  304. } else {
  305. data.start_tp = num;
  306. data.start_expr = expr;
  307. return [true, ''];
  308. }
  309. }
  310. }
  311. getExprInfo(field, converse = false) {
  312. const exprField = [
  313. {qty: 'tp', expr: 'expr'},
  314. {qty: 'start_tp', expr: 'start_expr'},
  315. {qty: 'range_qty', expr: 'range_expr'},
  316. ];
  317. if (converse) return _.find(exprField, { expr: field });
  318. return _.find(exprField, {qty: field});
  319. }
  320. getLeafOrder(data, parentReg, tree) {
  321. if (!data) return [];
  322. const defaultResult = data.uuid ? [`<<${data.uuid}>>`] : [];
  323. if (!data.expr) return defaultResult;
  324. const nodeParam = data.expr.match(this.nodeReg);
  325. if (!nodeParam || nodeParam.length === 0) return defaultResult;
  326. const result = [];
  327. for (const op of nodeParam) {
  328. const id = op.substring(2, op.length - 2);
  329. if (data.uuid === id || op === parentReg) {
  330. result.push(op);
  331. } else {
  332. const payNode = tree.nodes.find(x => {return x.uuid === id; });
  333. const subOrderParam = this.getLeafOrder(payNode, data.uuid ? `<<${data.uuid}>>` : parentReg, tree);
  334. result.push(...subOrderParam);
  335. }
  336. }
  337. return result;
  338. }
  339. checkCircularExpr(expr, selfId, tree) {
  340. const leafOrder = this.getLeafOrder({expr}, `<<${selfId}>>`, tree);
  341. if (leafOrder.indexOf(`<<${selfId}>>`) >= 0) return true;
  342. return false;
  343. }
  344. calculateExpr(expr) {
  345. let formula = expr;
  346. for (const b of this.bases) {
  347. formula = formula.replace(b.reg, b.value);
  348. }
  349. const percent = formula.match(this.percentReg);
  350. if (percent) {
  351. for (const p of percent) {
  352. const v = math.evaluate(p.replace(new RegExp('%', 'gm'), '/100'));
  353. formula = formula.replace(p, v);
  354. }
  355. }
  356. try {
  357. const value = ZhCalc.mathCalcExpr(formula);
  358. return value;
  359. } catch(err) {
  360. return 0;
  361. }
  362. }
  363. }
  364. return new PayCalc(b, a);
  365. })(calcBase, addBase);
  366. const payObj = (function() {
  367. const spread = SpreadJsObj.createNewSpread($('#pay-spread')[0]);
  368. const sheet = spread.getActiveSheet();
  369. const spreadSetting = {
  370. cols: [
  371. {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 230, formatter: '@', cellType: 'tree', getTip: payUtils.tips.name},
  372. {title: '本期金额(F)', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 2, width: 100, type: 'Number'},
  373. {title: '截止上期金额', colSpan: '1', rowSpan: '1', field: 'pre_tp', hAlign: 2, width: 100, readOnly: true, type: 'Number'},
  374. {title: '截止本期金额', colSpan: '1', rowSpan: '1', field: 'end_tp', hAlign: 2, width: 100, readOnly: true, type: 'Number'},
  375. {title: '起扣金额', colSpan: '1', rowSpan: '1', field: 'start_tp', hAlign: 2, width: 100, type: 'Number'},
  376. {title: '付(扣)款限额', colSpan: '1', rowSpan: '1', field: 'range_tp', hAlign: 2, width: 100, cellType: 'tip', type: 'Number', getTip: payUtils.tips.range_tp},
  377. {title: '汇总', colSpan: '1', rowSpan: '1', field: 'is_yf', hAlign: 2, width: 60, readOnly: true, type: 'checkbox'},
  378. {title: '附件', colSpan: '1', rowSpan: '1', field: 'attachment', hAlign: 0, width: 60, readOnly: true, cellType: 'imageBtn', normalImg: '#rela-file-icon', hoverImg: '#rela-file-hover', getValue: 'getValue.attachment'},
  379. {title: '本期批注', colSpan: '1', rowSpan: '1', field: 'postil', hAlign: 0, width: 120, formatter: '@', cellType: 'autoTip'},
  380. ],
  381. emptyRows: 0,
  382. headRows: 1,
  383. headRowHeight: [32],
  384. headColWidth: [30],
  385. defaultRowHeight: 21,
  386. headerFont: '12px 微软雅黑',
  387. font: '12px 微软雅黑',
  388. readOnly: readOnly,
  389. localCache: {
  390. key: 'phase-pay',
  391. colWidth: true,
  392. },
  393. pos: SpreadJsObj.getObjPos($('#pay-spread')[0]),
  394. };
  395. sjsSettingObj.setFxTreeStyle(spreadSetting, sjsSettingObj.FxTreeStyle.phasePay);
  396. SpreadJsObj.initSheet(sheet, spreadSetting);
  397. const payTree = createNewPathTree('base', {
  398. id: 'tree_id', pid: 'tree_pid', order: 'tree_order',
  399. level: 'tree_level', isLeaf: 'tree_is_leaf', fullPath: 'tree_full_path',
  400. rootId: -1,
  401. });
  402. const payEvent = {
  403. refreshActn: function() {
  404. const setObjEnable = function (obj, enable) {
  405. if (enable) {
  406. obj.removeClass('disabled');
  407. } else {
  408. obj.addClass('disabled');
  409. }
  410. };
  411. const select = SpreadJsObj.getSelectObject(sheet);
  412. if (!select) {
  413. setObjEnable($('a[name=base-opr][type=add]'), false);
  414. setObjEnable($('a[name=base-opr][type=del]'), false);
  415. setObjEnable($('a[name=base-opr][type=up-move]'), false);
  416. setObjEnable($('a[name=base-opr][type=down-move]'), false);
  417. return;
  418. }
  419. const preNode = payTree.getPreSiblingNode(select);
  420. setObjEnable($('a[name=base-opr][type=add]'), !readOnly && !payUtils.check.isSf(select) && !payUtils.check.isYf(select));
  421. const delValid = !payUtils.check.isFixed(select) && !payUtils.check.isStarted(select);
  422. setObjEnable($('a[name=base-opr][type=del]'), !readOnly && delValid);
  423. setObjEnable($('a[name=base-opr][type=up-move]'), !readOnly && !payUtils.check.isFixed(select) && preNode);
  424. setObjEnable($('a[name=base-opr][type=down-move]'), !readOnly && !payUtils.check.isFixed(select) && !payTree.isLastSibling(select));
  425. },
  426. loadExprToInput: function() {
  427. const sel = sheet.getSelections()[0];
  428. const col = sheet.zh_setting.cols[sel.col];
  429. const data = SpreadJsObj.getSelectObject(this.sheet);
  430. if (data) {
  431. if (col.field === 'tp') {
  432. $('#expr').val(data.expr).attr('field', 'expr').attr('org', data.expr)
  433. .attr('readOnly', readOnly|| payCol.readOnly.tp(data));
  434. } else if (col.field === 'stage_tp') {
  435. $('#expr').val(data.start_expr).attr('field', 'start_expr').attr('org', data.start_expr)
  436. .attr('readOnly', readOnly|| payCol.readOnly.sprice(data) || payBase.isYF(data));
  437. } else if (col.field === 'rprice') {
  438. $('#expr').val(data.range_expr).attr('field', 'range_expr').attr('org', data.range_expr)
  439. .attr('readOnly', readOnly|| payCol.readOnly.rprice(data) || payBase.isYF(data));
  440. } else {
  441. $('#expr').val('').attr('readOnly', true);
  442. }
  443. $('#expr').attr('data-row', sel.row);
  444. } else {
  445. $('#expr').val('').attr('readOnly', true);
  446. $('#expr').removeAttr('data-row');
  447. }
  448. },
  449. refreshTree: function (data) {
  450. SpreadJsObj.massOperationSheet(sheet, function () {
  451. const tree = sheet.zh_tree;
  452. // 处理删除
  453. if (data.delete) {
  454. data.delete.sort(function (a, b) {
  455. return b.deleteIndex - a.deleteIndex;
  456. });
  457. for (const d of data.delete) {
  458. sheet.deleteRows(d.deleteIndex, 1);
  459. }
  460. }
  461. // 处理新增
  462. if (data.create) {
  463. const newNodes = data.create;
  464. if (newNodes) {
  465. newNodes.sort(function (a, b) {
  466. return a.index - b.index;
  467. });
  468. for (const node of newNodes) {
  469. sheet.addRows(node.index, 1);
  470. SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(node), 1);
  471. }
  472. }
  473. }
  474. // 处理更新
  475. if (data.update) {
  476. const rows = [];
  477. for (const u of data.update) {
  478. rows.push(tree.nodes.indexOf(u));
  479. }
  480. SpreadJsObj.reLoadRowsData(sheet, rows);
  481. }
  482. });
  483. },
  484. editStarting: function(e, info) {
  485. const col = info.sheet.zh_setting.cols[info.col];
  486. const select = SpreadJsObj.getSelectObject(info.sheet);
  487. switch (col.field) {
  488. case 'name':
  489. info.cancel = payUtils.check.isFixed(select);
  490. break;
  491. case 'tp':
  492. case 'is_gather':
  493. info.cancel = select.children && select.children.length > 0;
  494. break;
  495. case 'start_tp':
  496. case 'range_tp':
  497. info.cancel = (select.children && select.children.length > 0) || payUtils.check.isYf(select);
  498. break;
  499. }
  500. if (col.field === 'tp') {
  501. if (select.expr && select.expr !== '') {
  502. info.sheet.getCell(info.row, info.col).text(payCalc.trans2OrderExpr(select.expr, payTree));
  503. }
  504. } else if (col.field === 'start_tp') {
  505. if (select.start_expr && select.start_expr !== '') {
  506. info.sheet.getCell(info.row, info.col).text(select.start_expr);
  507. }
  508. } else if (col.field === 'range_tp') {
  509. if (select.range_expr && select.range_expr !== '') {
  510. info.sheet.getCell(info.row, info.col).text(select.range_expr);
  511. }
  512. }
  513. },
  514. editEnded: function(e, info) {
  515. if (!info.sheet.zh_setting) return;
  516. const select = SpreadJsObj.getSelectObject(info.sheet);
  517. const col = info.sheet.zh_setting.cols[info.col];
  518. if (col.field === 'is_gather') return;
  519. // 未改变值则不提交
  520. const validText = info.editingText ? info.editingText.replace('\n', '') : '';
  521. let orgValue;
  522. if (col.field === 'tp') {
  523. orgValue = select.expr ? payCalc.trans2OrderExpr(select.expr, payTree) : select.tp;
  524. } else if (col.field === 'start_tp') {
  525. orgValue = select.start_expr ? select.start_expr : select.start_tp;
  526. } else if (col.field === 'range_tp') {
  527. orgValue = select.range_expr ? select.range_expr : select.range_tp;
  528. } else {
  529. orgValue = select[col.field];
  530. }
  531. orgValue = orgValue || '';
  532. if (orgValue == validText) {
  533. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  534. return;
  535. }
  536. const data = { postType: 'update', postData: { id: select.id } };
  537. switch(col.field) {
  538. case 'tp':
  539. const [tpValid, tpMsg] = payUtils.check.isSf(select)
  540. ? payCalc.checkSfExpr(validText, data.postData, select, payTree)
  541. : payCalc.checkExpr(validText, data.postData, select, payTree);
  542. if (!tpValid) {
  543. toastr.warning(tpMsg);
  544. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  545. return;
  546. }
  547. break;
  548. case 'start_tp':
  549. const [sValid, sMsg] = payCalc.checkStartExpr(select, validText, data.postData);
  550. if (!sValid) {
  551. toastr.warning(sMsg);
  552. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  553. return;
  554. }
  555. break;
  556. case 'range_tp':
  557. const [rValid, rMsg] = payCalc.checkRangeExpr(select, validText, data.postData);
  558. if (!rValid) {
  559. toastr.warning(rMsg);
  560. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  561. return;
  562. }
  563. break;
  564. default:
  565. if (col.type === 'Number') {
  566. data.postData[col.field] = _.toNumber(validText) || 0;
  567. } else {
  568. data.postData[col.field] = validText || '';
  569. }
  570. break;
  571. }
  572. postData('update', data, function (result) {
  573. if (result.reload) {
  574. payEvent.reloadPays(result.reload);
  575. } else {
  576. const refreshData = payTree.loadPostData(result);
  577. payEvent.refreshTree(refreshData);
  578. }
  579. }, function () {
  580. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  581. });
  582. },
  583. selectionChanged: function(e, info) {
  584. if (info.newSelections) {
  585. if (!info.oldSelections || info.newSelections[0].row !== info.oldSelections[0].row) {
  586. payEvent.refreshActn();
  587. }
  588. }
  589. payEvent.loadExprToInput();
  590. },
  591. baseOpr: function(type) {
  592. const self = this;
  593. const node = SpreadJsObj.getSelectObject(sheet);
  594. if (type === 'delete') {
  595. postData('update', { postType: 'delete', postData: { id: node.tree_id }}, function(result) {
  596. payEvent.reloadPays(result.reload);
  597. });
  598. } else {
  599. postData('update', { postType: type, postData: { id: node.tree_id }}, function (result) {
  600. const refreshData = payTree.loadPostData(result);
  601. payEvent.refreshTree(refreshData);
  602. const sel = sheet.getSelections()[0];
  603. if (sel) {
  604. if (['up-move', 'down-move'].indexOf(type) > -1) {
  605. sheet.setSelection(payTree.getNodeIndex(node), sel.col, sel.rowCount, sel.colCount);
  606. SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, payTree.getNodeIndex(node)]);
  607. } else if (type === 'add') {
  608. sheet.setSelection(payTree.getNodeIndex(refreshData.create[0]), sel.col, sel.rowCount, sel.colCount);
  609. SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, payTree.getNodeIndex(refreshData.create[0])]);
  610. }
  611. }
  612. self.refreshActn(sheet);
  613. });
  614. }
  615. },
  616. reloadPays: function(datas){
  617. payTree.loadDatas(datas);
  618. SpreadJsObj.loadSheetData(sheet, SpreadJsObj.DataType.Tree, payTree);
  619. payEvent.refreshActn();
  620. }
  621. };
  622. spread.bind(spreadNS.Events.SelectionChanged, payEvent.selectionChanged);
  623. if (!readOnly) {
  624. spread.bind(spreadNS.Events.EditStarting, payEvent.editStarting);
  625. spread.bind(spreadNS.Events.EditEnded, payEvent.editEnded);
  626. $('a[name="base-opr"]').click(function () {
  627. payEvent.baseOpr(this.getAttribute('type'));
  628. });
  629. $('')
  630. }
  631. return { spread, sheet, payTree, loadDatas: payEvent.reloadPays }
  632. })();
  633. payObj.loadDatas(details);
  634. // todo 加载审批列表
  635. $.subMenu({
  636. menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
  637. toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
  638. key: 'menu.1.0.0',
  639. miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
  640. callback: function (info) {
  641. if (info.mini) {
  642. $('.panel-title').addClass('fluid');
  643. $('#sub-menu').removeClass('panel-sidebar');
  644. } else {
  645. $('.panel-title').removeClass('fluid');
  646. $('#sub-menu').addClass('panel-sidebar');
  647. }
  648. autoFlashHeight();
  649. payObj.spread.refresh();
  650. }
  651. });
  652. });