phase_pay_detail.js 38 KB

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