phase_pay_detail.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. 'use strict';
  2. const showSideTools = function (show) {
  3. const left = $('#left-view'), right = $('#right-view'), parent = left.parent();
  4. if (show) {
  5. right.show();
  6. autoFlashHeight();
  7. /**
  8. * right.show()后, parent被撑开成2倍left.height, 导致parent.width减少了10px
  9. * 第一次left.width调整后,parent的缩回left.height, 此时parent.width又增加了10px
  10. * 故需要通过最终的parent.width再计算一次left.width
  11. *
  12. * Q: 为什么不通过先计算left.width的宽度,以避免计算两次left.width?
  13. * A: 右侧工具栏不一定显示,当右侧工具栏显示过一次后,就必须使用parent和right来计算left.width
  14. *
  15. */
  16. //left.css('width', parent.width() - right.outerWidth());
  17. //left.css('width', parent.width() - right.outerWidth());
  18. const percent = 100 - right.outerWidth() /parent.width() * 100;
  19. left.css('width', percent + '%');
  20. } else {
  21. left.width(parent.width());
  22. right.hide();
  23. }
  24. };
  25. $(document).ready(() => {
  26. autoFlashHeight();
  27. const payUtils = {
  28. tips: {
  29. name: function(data) {
  30. const tips = [];
  31. if (data) {
  32. if (data.pause) tips.push('当前项已停用');
  33. if (!data.is_yf) tips.push('当前项不参与本期应付计算');
  34. }
  35. return tips.join('<br/>');
  36. },
  37. range_tp: function (data) {
  38. if (!data || (!data.range_expr && !data.range_tp) || !data.dl_type) return '';
  39. if (data.dl_type === 1) {
  40. return '计提期限为(当 计量期数 ≥ ' + data.dl_count + ')';
  41. } else if (data.dl_type === 2) {
  42. switch (data.dl_tp_type) {
  43. case 'contract':
  44. return '计提期限为(累计合同计量 ≥ ' + data.dl_tp + ')';
  45. case 'qc':
  46. return '计提期限为(累计变更计量 ≥ ' + data.dl_tp + ')';
  47. case 'gather':
  48. return '计提期限为(累计完成计量 ≥ ' + data.dl_tp + ')';
  49. }
  50. }
  51. }
  52. },
  53. check: {
  54. isFixed: function(data) {
  55. return data.is_fixed;
  56. },
  57. isStarted: function (data) {
  58. return data.pre_used;
  59. },
  60. isYf: function(data) {
  61. return data.pay_type === 'bqyf';
  62. },
  63. isSf: function(data) {
  64. return data.pay_type === 'bqsf';
  65. },
  66. isGatherValid: function(data) {
  67. return !data.pay_type && (!data.children || data.children.length === 0);
  68. },
  69. isOwner: function(data) {
  70. return data.create_user_id === userID;
  71. },
  72. isFinish: function(data) {
  73. return data.pre_finish;
  74. },
  75. isYB: function() {
  76. return userID === phasePay.create_user_id;
  77. },
  78. isOld: function(data) {
  79. return data.phase_id !== data.create_phase_id;
  80. },
  81. isLock: function (data) {
  82. const result = !!lockPayExpr && payUtils.check.isStarted(data) && payCalc.hasBase(data.expr);
  83. return result;
  84. },
  85. tpReadOnly: function(data) {
  86. return payUtils.check.isYf(data) || payUtils.check.isLock(data);
  87. },
  88. startTpReadOnly: function(data) {
  89. if (payUtils.check.isOld(data)) {
  90. return payUtils.check.isStarted(data) || !payUtils.check.isYB(data) || payUtils.check.isLock(data);
  91. } else {
  92. return payUtils.check.isWC(data) || payUtils.check.isSF(data) || payUtils.check.isYf(data) || !(payUtils.check.isOwner(data) || payUtils.check.isYB());
  93. }
  94. },
  95. rangeTpReadOnly: function(data) {
  96. if (payUtils.check.isOld(data)) {
  97. return !payUtils.check.isYB(data) || payUtils.check.isLock(data);
  98. } else {
  99. return payUtils.check.isWC(data) || payUtils.check.isYF(data) || !(payUtils.check.isOwner(data) || payUtils.check.isYB());
  100. }
  101. },
  102. },
  103. menuVisible: {
  104. pause: function (data) {
  105. if (payUtils.check.isOld(data)) {
  106. return payUtils.check.isYB();
  107. } else {
  108. return payUtils.check.isOwner(data) || payUtils.check.isYB();
  109. }
  110. },
  111. deadline: function (data) {
  112. if (payUtils.check.isOld(data)) {
  113. return !payUtils.check.isFinish(data) && payUtils.check.isYB();
  114. } else {
  115. return payUtils.check.isOwner(data) || payUtils.check.isYB();
  116. }
  117. }
  118. },
  119. };
  120. const payCalc = (function (b, a) {
  121. class PayCalc {
  122. constructor (bases, add) {
  123. this.percentReg = /((\d+)|((\d+)(\.\d+)))%/g;
  124. this.bases = bases;
  125. this.bases.sort(function (a, b) {
  126. return a.sort - b.sort;
  127. });
  128. for (const b of this.bases) {
  129. b.reg = new RegExp(b.code, 'igm');
  130. }
  131. this.addBase = add;
  132. this.orderReg = /f\d+/ig;
  133. this.nodeReg = /<<[a-z0-9\-]+>>/ig;
  134. this.firstNodeReg = /^<<[a-z0-9\-]+>>/ig;
  135. }
  136. hasBase(expr) {
  137. if (!expr) return false;
  138. for (const b of this.bases) {
  139. if (data.expr.indexOf(b.code) >= 0) return true;
  140. }
  141. return false;
  142. }
  143. trans2OrderExpr(expr, payTree) {
  144. const nodeParam = expr.match(this.nodeReg);
  145. if (nodeParam) {
  146. for (const op of nodeParam) {
  147. const id = op.substring(2, op.length - 2);
  148. const payNode = payTree.nodes.find(x => { return x.uuid === id; });
  149. expr = expr.replace(op, payNode ? `f${payTree.getNodeIndex(payNode) + 1}` || '' : 0);
  150. }
  151. }
  152. return expr;
  153. }
  154. trans2NodeExpr(expr, payTree) {
  155. const orderParam = expr.match(this.orderReg);
  156. if (orderParam) {
  157. for (const op of orderParam) {
  158. const order = parseInt(op.substring(1, op.length));
  159. const payNode = payTree.nodes[order - 1];
  160. expr = expr.replace(op, payNode ? `<<${payNode.uuid}>>` || '' : 0);
  161. }
  162. }
  163. return expr;
  164. }
  165. checkExprValid(expr, invalidParam, selfId, payTree) {
  166. if (!expr) return [true, ''];
  167. const param = [];
  168. let num = '', base = '';
  169. let fixedIdParam;
  170. for (let i = 0, iLen = expr.length; i < iLen; i++) {
  171. const subExpr = expr.substring(i, expr.length);
  172. if (/^[\d\.%]+/.test(expr[i])) {
  173. if (base !== '') {
  174. param.push({type: 'base', value: base});
  175. base = '';
  176. }
  177. num = num + expr[i];
  178. } else if (this.firstNodeReg.test(subExpr)) {
  179. if (num !== '') {
  180. param.push({type: 'num', value: num});
  181. num = '';
  182. }
  183. if (base !== '') {
  184. param.push({type: 'base', value: base});
  185. base = '';
  186. }
  187. // const node = this.nodeReg.exec(subExpr);
  188. const node = subExpr.match(this.firstNodeReg);
  189. param.push({type: 'node', value: node[0]});
  190. i = i + node[0].length - 1;
  191. } else if (/^[a-z]/.test(expr[i])) {
  192. if (num !== '') {
  193. param.push({type: 'num', value: num});
  194. num = '';
  195. }
  196. base = base + expr[i];
  197. } else if (expr[i] === '(') {
  198. if (num !== '') {
  199. param.push({type: 'num', value: num});
  200. num = '';
  201. }
  202. if (base !== '') {
  203. param.push({type: 'base', value: base});
  204. base = '';
  205. }
  206. param.push({type: 'left', value: '('});
  207. } else if (expr[i] === ')') {
  208. if (num !== '') {
  209. param.push({type: 'num', value: num});
  210. num = '';
  211. }
  212. if (base !== '') {
  213. param.push({type: 'base', value: base});
  214. base = '';
  215. }
  216. param.push({type: 'right', value: ')'});
  217. } else if (/^[\+\-*\/]/.test(expr[i])) {
  218. if (num !== '') {
  219. param.push({type: 'num', value: num});
  220. num = '';
  221. }
  222. if (base !== '') {
  223. param.push({type: 'base', value: base});
  224. base = '';
  225. }
  226. param.push({type: 'calc', value: expr[i]});
  227. } else {
  228. return [false, '输入的表达式含有非法字符: ' + expr[i]];
  229. }
  230. }
  231. if (num !== '') {
  232. param.push({type: 'num', value: num});
  233. num = '';
  234. }
  235. if (base !== '') {
  236. param.push({type: 'base', value: base});
  237. base = '';
  238. }
  239. if (param.length === 0) return [true, ''];
  240. if (param.length > 1) {
  241. if (param[0].value === '-' && param[1].type === 'num') {
  242. param[1].value = '-' + param[1].value;
  243. param.shift();
  244. }
  245. }
  246. const iLen = param.length;
  247. let iLeftCount = 0, iRightCount = 0;
  248. for (const [i, p] of param.entries()) {
  249. if (p.type === 'calc') {
  250. if (i === 0 || i === iLen - 1)
  251. return [false, '输入的表达式非法:计算符号' + p.value + '前后应有数字或计算基数'];
  252. }
  253. if (p.type === 'num') {
  254. num = p.value.replace('%', '');
  255. if (p.value.length - num.length > 1)
  256. return [false, '输入的表达式非法:' + p.value + '不是一个有效的数字'];
  257. num = _.toNumber(num);
  258. if (num === undefined || num === null || _.isNaN(num))
  259. return [false, '输入的表达式非法:' + p.value + '不是一个有效的数字'];
  260. if (i > 0) {
  261. if (param[i - 1].type !== 'calc' && param[i - 1].type !== 'left') {
  262. return [false, '输入的表达式非法:' + p.value + '前应有运算符'];
  263. } else if (param[i - 1].value === '/' && num === 0) {
  264. return [false, '输入的表达式非法:请勿除0'];
  265. }
  266. }
  267. }
  268. if (p.type === 'base') {
  269. const baseParam = _.find(calcBase, {code: p.value});
  270. if (!baseParam)
  271. return [false, '输入的表达式非法:不存在计算基数' + p.value];
  272. if (invalidParam && invalidParam.indexOf(p.value) >= 0)
  273. return [false, '不可使用计算基数' + p.value];
  274. if (i > 0 && (param[i - 1].type === 'num' || param[i - 1].type === 'right'))
  275. return [false, '输入的表达式非法:' + p.value + '前应有运算符'];
  276. }
  277. if (p.type === 'node') {
  278. if (!selfId) return [false, '输入的表达式错误:不支持行号引用'];
  279. if ([`<<${selfId}>>`].indexOf(p.value) >= 0) return [false, '输入的表达式非法:请勿引用自己'];
  280. if (!fixedIdParam) {
  281. fixedIdParam = payTree.nodes.filter(x => { return x.is_fixed; }).map(x => { return `<<${x.uuid}>>`});
  282. }
  283. if (fixedIdParam.indexOf(p.value) >= 0) return [false, '输入的表达式非法:请勿引用固定项'];
  284. }
  285. if (p.type === 'left') {
  286. iLeftCount += 1;
  287. if (i !== 0 && (param[i-1].type !== 'calc' || param[i-1].type !== 'left'))
  288. return [false, '输入的表达式非法:(前应有运算符'];
  289. }
  290. if (p.type === 'right') {
  291. iRightCount += 1;
  292. if (i !== iLen - 1 && param[i+1].type !== 'calc')
  293. return [false, '输入的表达式非法:)后应有运算符'];
  294. if (iRightCount > iLeftCount)
  295. return [false, '输入的表达式非法:")"前无对应的"("'];
  296. }
  297. }
  298. if (iLeftCount > iRightCount)
  299. return [false, '输入的表达式非法:"("后无对应的")"'];
  300. if (selfId) {
  301. const circular = payCalc.checkCircularExpr(expr, selfId, payTree);
  302. // 当前循环计算不检查父项
  303. if (circular) return [false, '输入的表达式非法:循环引用'];
  304. }
  305. return [true, ''];
  306. }
  307. checkSfExpr(text, data, payNode, payTree) {
  308. if (text) {
  309. const num = _.toNumber(text);
  310. if (num) {
  311. data.expr = num;
  312. } else {
  313. const expr = this.trans2NodeExpr($.trim(text).replace('\t', '').replace('=', '').toLowerCase(), payTree);
  314. const [valid, msg] = this.checkExprValid(expr, [], payNode.uuid, payTree);
  315. if (!valid) return [valid, msg];
  316. data.expr = expr;
  317. }
  318. } else {
  319. data.tp = 0;
  320. data.expr = '';
  321. }
  322. return [true, ''];
  323. }
  324. checkExpr(text, data, payNode, payTree) {
  325. if (text) {
  326. const num = _.toNumber(text);
  327. if (num) {
  328. data.tp = num;
  329. data.expr = '';
  330. } else {
  331. const expr = this.trans2NodeExpr($.trim(text).replace('\t', '').replace('=', '').toLowerCase(), payTree);
  332. const [valid, msg] = this.checkExprValid(expr, ['bqyf'], payNode.uuid, payTree);
  333. if (!valid) return [valid, msg];
  334. data.expr = expr;
  335. data.tp = 0;
  336. }
  337. } else {
  338. data.tp = 0;
  339. data.expr = '';
  340. }
  341. return [true, ''];
  342. }
  343. checkRangeExpr(payNode, text, data) {
  344. if (!payNode) return [false, '数据错误'];
  345. const num = text ? _.toNumber(text) : 0;
  346. let expr = text ? (num ? '' : text) : '';
  347. expr = expr ? $.trim(expr).replace('\t', '').replace('=', '').toLowerCase() : '';
  348. const [valid, msg] = this.checkExprValid(expr, ['bqwc', 'ybbqwc', 'bqht', 'bqbg', 'bqyf']);
  349. if (!valid) return [valid, msg];
  350. if (payUtils.check.isStarted(payNode)) {
  351. if (payUtils.check.isSf(payNode)) {
  352. const value = expr ? payCalc.calculateExpr(expr) : num;
  353. if (payNode.pre_tp && value < payNode.pre_tp) return [false, '截止上期已计量' + payNode.pre_tp + ',扣款限额请勿少于改值'];
  354. data.range_tp = num;
  355. data.range_expr = expr;
  356. return [true, ''];
  357. } else {
  358. // if (payNode.pre_finish) return [false, '已达扣款限额,请勿修改'];
  359. // const value = expr ? payCalc.calculateExpr(expr) : num;
  360. // if (payNode.pre_tp && value < payNode.pre_tp) return [false, '截止上期已计量' + payNode.pre_tp + ',扣款限额请勿少于改值'];
  361. // data.range_tp = num;
  362. // data.range_expr = expr;
  363. return [false, '已经开始使用,请勿修改扣款限额'];
  364. }
  365. } else {
  366. data.range_tp = num;
  367. data.range_expr = expr;
  368. return [true, ''];
  369. }
  370. }
  371. checkStartExpr(payNode, text, data) {
  372. if (!payNode) return [false, '数据错误'];
  373. const num = text ? _.toNumber(text) : 0;
  374. let expr = text ? (num ? '' : text) : '';
  375. expr = expr ? $.trim(expr).replace('\t', '').replace('=', '').toLowerCase() : '';
  376. const [valid, msg] = this.checkExprValid(expr, ['bqwc', 'ybbqwc', 'bqht', 'bqbg', 'bqyf']);
  377. if (!valid) return [valid, msg];
  378. if (payUtils.check.isStarted(payNode)) {
  379. return [false, '已经开始计量,请勿修改起扣金额'];
  380. } else {
  381. if (this.addBase.pre_gather_tp) {
  382. const value = expr ? payCalc.calculateExpr(expr) : num;
  383. if (this.addBase.pre_gather_tp && value < this.addBase.pre_gather_tp)
  384. return [false, '起扣金额请勿少于本期完成截止上期计量金额' + this.addBase.pre_gather_tp];
  385. data.start_tp = num;
  386. data.start_expr = expr;
  387. return [true, ''];
  388. } else {
  389. data.start_tp = num;
  390. data.start_expr = expr;
  391. return [true, ''];
  392. }
  393. }
  394. }
  395. getExprInfo(field, converse = false) {
  396. const exprField = [
  397. {qty: 'tp', expr: 'expr'},
  398. {qty: 'start_tp', expr: 'start_expr'},
  399. {qty: 'range_qty', expr: 'range_expr'},
  400. ];
  401. if (converse) return _.find(exprField, { expr: field });
  402. return _.find(exprField, {qty: field});
  403. }
  404. getLeafOrder(data, parentReg, tree) {
  405. if (!data) return [];
  406. const defaultResult = data.uuid ? [`<<${data.uuid}>>`] : [];
  407. if (!data.expr) return defaultResult;
  408. const nodeParam = data.expr.match(this.nodeReg);
  409. if (!nodeParam || nodeParam.length === 0) return defaultResult;
  410. const result = [];
  411. for (const op of nodeParam) {
  412. const id = op.substring(2, op.length - 2);
  413. if (data.uuid === id || op === parentReg) {
  414. result.push(op);
  415. } else {
  416. const payNode = tree.nodes.find(x => {return x.uuid === id; });
  417. const subOrderParam = this.getLeafOrder(payNode, data.uuid ? `<<${data.uuid}>>` : parentReg, tree);
  418. result.push(...subOrderParam);
  419. }
  420. }
  421. return result;
  422. }
  423. checkCircularExpr(expr, selfId, tree) {
  424. const leafOrder = this.getLeafOrder({expr}, `<<${selfId}>>`, tree);
  425. if (leafOrder.indexOf(`<<${selfId}>>`) >= 0) return true;
  426. return false;
  427. }
  428. calculateExpr(expr) {
  429. let formula = expr;
  430. for (const b of this.bases) {
  431. formula = formula.replace(b.reg, b.value);
  432. }
  433. const percent = formula.match(this.percentReg);
  434. if (percent) {
  435. for (const p of percent) {
  436. const v = math.evaluate(p.replace(new RegExp('%', 'gm'), '/100'));
  437. formula = formula.replace(p, v);
  438. }
  439. }
  440. try {
  441. const value = ZhCalc.mathCalcExpr(formula);
  442. return value;
  443. } catch(err) {
  444. return 0;
  445. }
  446. }
  447. refreshBaseHtml() {
  448. const html = [];
  449. for (const [i, b] of this.bases.entries()) {
  450. html.push('<tr>');
  451. html.push(`<td>${i+1}</td><td>${b.name}</td><td>${b.code}</td>`);
  452. if (b.code === 'bqyf') {
  453. html.push('<td class="text-right">--</td>');
  454. } else {
  455. html.push(`<td class="text-right">${b.formatValue}</td>`);
  456. }
  457. html.push('</tr>');
  458. }
  459. $('#base-list').html(html.join(''));
  460. }
  461. reloadBase(bases, add) {
  462. this.bases = bases;
  463. this.refreshBaseHtml();
  464. this.bases.sort(function (a, b) {
  465. return a.sort - b.sort;
  466. });
  467. for (const b of this.bases) {
  468. b.reg = new RegExp(b.code, 'igm');
  469. }
  470. this.addBase = add;
  471. }
  472. }
  473. return new PayCalc(b, a);
  474. })(calcBase, addBase);
  475. const payObj = (function() {
  476. const spread = SpreadJsObj.createNewSpread($('#pay-spread')[0]);
  477. const sheet = spread.getActiveSheet();
  478. const spreadSetting = {
  479. cols: [
  480. {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 230, formatter: '@', cellType: 'tree', getTip: payUtils.tips.name},
  481. {title: '本期金额(F)', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 2, width: 100, type: 'Number'},
  482. {title: '截止上期金额', colSpan: '1', rowSpan: '1', field: 'pre_tp', hAlign: 2, width: 100, readOnly: true, type: 'Number'},
  483. {title: '截止本期金额', colSpan: '1', rowSpan: '1', field: 'end_tp', hAlign: 2, width: 100, readOnly: true, type: 'Number'},
  484. {title: '起扣金额', colSpan: '1', rowSpan: '1', field: 'start_tp', hAlign: 2, width: 100, type: 'Number'},
  485. {title: '付(扣)款限额', colSpan: '1', rowSpan: '1', field: 'range_tp', hAlign: 2, width: 100, cellType: 'tip', type: 'Number', getTip: payUtils.tips.range_tp},
  486. {title: '汇总', colSpan: '1', rowSpan: '1', field: 'is_gather', hAlign: 1, width: 60, cellType: 'signalCheckbox', show: payUtils.check.isGatherValid},
  487. {title: '本期批注', colSpan: '1', rowSpan: '1', field: 'postil', hAlign: 0, width: 120, formatter: '@', cellType: 'autoTip'},
  488. ],
  489. emptyRows: 0,
  490. headRows: 1,
  491. headRowHeight: [32],
  492. headColWidth: [30],
  493. defaultRowHeight: 21,
  494. headerFont: '12px 微软雅黑',
  495. font: '12px 微软雅黑',
  496. readOnly: readOnly,
  497. localCache: {
  498. key: 'phase-pay',
  499. colWidth: true,
  500. },
  501. pos: SpreadJsObj.getObjPos($('#pay-spread')[0]),
  502. getColor: function (sheet, data, row, col, defaultColor) {
  503. if (!data) return defaultColor;
  504. if (data.expr && data.expr.indexOf('#ref!') >= 0) {
  505. return spreadColor.pay.expr_err;
  506. } else if (data.is_pause) {
  507. return '#f2f2f2';
  508. } else if (data.create_phase_order > 1 && data.create_phase_order === phasePay.phase_order) {
  509. return '#FFFFE1';
  510. } else {
  511. return defaultColor;
  512. }
  513. }
  514. };
  515. sjsSettingObj.setFxTreeStyle(spreadSetting, sjsSettingObj.FxTreeStyle.phasePay);
  516. SpreadJsObj.initSheet(sheet, spreadSetting);
  517. const payTree = createNewPathTree('base', {
  518. id: 'tree_id', pid: 'tree_pid', order: 'tree_order',
  519. level: 'tree_level', isLeaf: 'tree_is_leaf', fullPath: 'tree_full_path',
  520. rootId: -1,
  521. });
  522. const payEvent = {
  523. refreshActn: function() {
  524. const setObjEnable = function (obj, enable) {
  525. if (enable) {
  526. obj.removeClass('disabled');
  527. } else {
  528. obj.addClass('disabled');
  529. }
  530. };
  531. const select = SpreadJsObj.getSelectObject(sheet);
  532. if (!select) {
  533. setObjEnable($('a[name=base-opr][type=add]'), false);
  534. setObjEnable($('a[name=base-opr][type=del]'), false);
  535. setObjEnable($('a[name=base-opr][type=up-move]'), false);
  536. setObjEnable($('a[name=base-opr][type=down-move]'), false);
  537. return;
  538. }
  539. const preNode = payTree.getPreSiblingNode(select);
  540. setObjEnable($('a[name=base-opr][type=add]'), !readOnly && !payUtils.check.isSf(select) && !payUtils.check.isYf(select));
  541. const delValid = !payUtils.check.isFixed(select) && !payUtils.check.isStarted(select);
  542. setObjEnable($('a[name=base-opr][type=delete]'), !readOnly && delValid);
  543. setObjEnable($('a[name=base-opr][type=up-move]'), !readOnly && !payUtils.check.isFixed(select) && preNode);
  544. setObjEnable($('a[name=base-opr][type=down-move]'), !readOnly && !payUtils.check.isFixed(select) && !payTree.isLastSibling(select));
  545. },
  546. loadExprToInput: function() {
  547. const sel = sheet.getSelections()[0];
  548. const col = sheet.zh_setting.cols[sel.col];
  549. const data = SpreadJsObj.getSelectObject(sheet);
  550. if (data && (!data.children || data.children.length === 0)) {
  551. if (col.field === 'tp') {
  552. const expr = payCalc.trans2OrderExpr(data.expr, payTree);
  553. $('#pay-expr').val(expr).attr('field', 'expr').attr('org', expr)
  554. .attr('readOnly', readOnly|| payUtils.check.tpReadOnly(data));
  555. } else if (col.field === 'start_tp') {
  556. const expr = payCalc.trans2OrderExpr(data.start_expr, payTree) || data.start_tp;
  557. $('#pay-expr').val(expr).attr('field', 'start_expr').attr('org', expr)
  558. .attr('readOnly', readOnly|| payUtils.check.startTpReadOnly(data) || payUtils.check.isYf(data));
  559. } else if (col.field === 'range_tp') {
  560. const expr = payCalc.trans2OrderExpr(data.range_expr, payTree);
  561. $('#pay-expr').val(expr).attr('field', 'range_expr').attr('org', expr)
  562. .attr('readOnly', readOnly|| payUtils.check.rangeTpReadOnly(data) || payUtils.check.isYf(data));
  563. } else {
  564. $('#pay-expr').val('').attr('readOnly', true);
  565. }
  566. $('#pay-expr').attr('data-row', sel.row);
  567. } else {
  568. $('#pay-expr').val('').attr('readOnly', true);
  569. $('#pay-expr').removeAttr('data-row');
  570. }
  571. },
  572. refreshTree: function (data) {
  573. SpreadJsObj.massOperationSheet(sheet, function () {
  574. const tree = sheet.zh_tree;
  575. // 处理删除
  576. if (data.delete) {
  577. data.delete.sort(function (a, b) {
  578. return b.deleteIndex - a.deleteIndex;
  579. });
  580. for (const d of data.delete) {
  581. sheet.deleteRows(d.deleteIndex, 1);
  582. }
  583. }
  584. // 处理新增
  585. if (data.create) {
  586. const newNodes = data.create;
  587. if (newNodes) {
  588. newNodes.sort(function (a, b) {
  589. return a.index - b.index;
  590. });
  591. for (const node of newNodes) {
  592. sheet.addRows(node.index, 1);
  593. SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(node), 1);
  594. }
  595. }
  596. }
  597. // 处理更新
  598. if (data.update) {
  599. const rows = [];
  600. for (const u of data.update) {
  601. rows.push(tree.nodes.indexOf(u));
  602. }
  603. SpreadJsObj.reLoadRowsData(sheet, rows);
  604. }
  605. });
  606. },
  607. editStarting: function(e, info) {
  608. const col = info.sheet.zh_setting.cols[info.col];
  609. const select = SpreadJsObj.getSelectObject(info.sheet);
  610. switch (col.field) {
  611. case 'name':
  612. info.cancel = payUtils.check.isFixed(select);
  613. break;
  614. case 'tp':
  615. case 'is_gather':
  616. info.cancel = !payUtils.check.isGatherValid(select);
  617. break;
  618. case 'start_tp':
  619. case 'range_tp':
  620. info.cancel = (select.children && select.children.length > 0) || payUtils.check.isYf(select);
  621. break;
  622. case 'is_gather':
  623. info.cancel = true;
  624. break;
  625. }
  626. if (col.field === 'tp') {
  627. if (select.expr && select.expr !== '') {
  628. info.sheet.getCell(info.row, info.col).text(payCalc.trans2OrderExpr(select.expr, payTree));
  629. }
  630. } else if (col.field === 'start_tp') {
  631. if (select.start_expr && select.start_expr !== '') {
  632. info.sheet.getCell(info.row, info.col).text(select.start_expr);
  633. }
  634. } else if (col.field === 'range_tp') {
  635. if (select.range_expr && select.range_expr !== '') {
  636. info.sheet.getCell(info.row, info.col).text(select.range_expr);
  637. }
  638. }
  639. },
  640. editEnded: function(e, info) {
  641. if (!info.sheet.zh_setting) return;
  642. const select = SpreadJsObj.getSelectObject(info.sheet);
  643. const col = info.sheet.zh_setting.cols[info.col];
  644. if (col.field === 'is_gather') return;
  645. // 未改变值则不提交
  646. const validText = info.editingText ? info.editingText.replace('\n', '') : '';
  647. let orgValue;
  648. if (col.field === 'tp') {
  649. orgValue = select.expr ? payCalc.trans2OrderExpr(select.expr, payTree) : select.tp;
  650. } else if (col.field === 'start_tp') {
  651. orgValue = select.start_expr ? select.start_expr : select.start_tp;
  652. } else if (col.field === 'range_tp') {
  653. orgValue = select.range_expr ? select.range_expr : select.range_tp;
  654. } else {
  655. orgValue = select[col.field];
  656. }
  657. orgValue = orgValue || '';
  658. if (orgValue == validText) {
  659. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  660. return;
  661. }
  662. const data = { postType: 'update', postData: { id: select.id } };
  663. switch(col.field) {
  664. case 'tp':
  665. const [tpValid, tpMsg] = payUtils.check.isSf(select)
  666. ? payCalc.checkSfExpr(validText, data.postData, select, payTree)
  667. : payCalc.checkExpr(validText, data.postData, select, payTree);
  668. if (!tpValid) {
  669. toastr.warning(tpMsg);
  670. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  671. return;
  672. }
  673. break;
  674. case 'start_tp':
  675. const [sValid, sMsg] = payCalc.checkStartExpr(select, validText, data.postData);
  676. if (!sValid) {
  677. toastr.warning(sMsg);
  678. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  679. return;
  680. }
  681. break;
  682. case 'range_tp':
  683. const [rValid, rMsg] = payCalc.checkRangeExpr(select, validText, data.postData);
  684. if (!rValid) {
  685. toastr.warning(rMsg);
  686. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  687. return;
  688. }
  689. break;
  690. default:
  691. if (col.type === 'Number') {
  692. data.postData[col.field] = _.toNumber(validText) || 0;
  693. } else {
  694. data.postData[col.field] = validText || '';
  695. }
  696. break;
  697. }
  698. postData('update', data, function (result) {
  699. if (result.reload) {
  700. payEvent.reloadPays(result.reload);
  701. } else {
  702. const refreshData = payTree.loadPostData(result);
  703. payEvent.refreshTree(refreshData);
  704. }
  705. }, function () {
  706. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  707. });
  708. },
  709. selectionChanged: function(e, info) {
  710. if (info.newSelections) {
  711. if (!info.oldSelections || info.newSelections[0].row !== info.oldSelections[0].row) {
  712. payEvent.refreshActn();
  713. }
  714. }
  715. payEvent.loadExprToInput();
  716. },
  717. buttonClicked: function (e, info) {
  718. if (!info.sheet.zh_setting) return;
  719. const select = SpreadJsObj.getSelectObject(info.sheet);
  720. const col = info.sheet.zh_setting.cols[info.col];
  721. if (col.field !== 'is_gather') return;
  722. if (!payUtils.check.isGatherValid(select)) return;
  723. if (info.sheet.isEditing()) info.sheet.endEdit(true);
  724. const data = {
  725. postType: 'update',
  726. postData: { id: select.id },
  727. };
  728. data.postData[col.field] = info.sheet.getValue(info.row, info.col) || 0;
  729. // 更新至服务器
  730. postData('update', data, function (result) {
  731. if (result.reload) payEvent.reloadPays(result.reload);
  732. });
  733. },
  734. deletePress: function (sheet) {
  735. if (!sheet.zh_setting) return;
  736. const sel = sheet.getSelections()[0];
  737. if (!sel) return;
  738. const col = sheet.zh_setting.cols[sel.col];
  739. if (col.readOnly === true) return;
  740. if (sel.colCount > 1) toastr.warning('请勿同时删除多列数据');
  741. const data = { postType: 'update', postData: [] };
  742. for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow ++) {
  743. const node = sheet.zh_tree.nodes[iRow];
  744. if (node && (!node.pay_type || col.field === 'postil')) {
  745. const updateData = { id: node.id };
  746. switch(col.field) {
  747. case 'tp':
  748. updateData.tp = 0;
  749. updateData.expr = '';
  750. break;
  751. case 'start_tp':
  752. updateData.start_tp = 0;
  753. updateData.start_expr = '';
  754. break;
  755. case 'range_tp':
  756. updateData.range_tp = 0;
  757. updateData.range_expr = '';
  758. break;
  759. case 'is_gather':
  760. updateData.is_gather = 0;
  761. break;
  762. default:
  763. updateData[col.field] = col.type === 'Number' ? 0 : '';
  764. }
  765. data.postData.push(updateData);
  766. }
  767. }
  768. postData('update', data, function (result) {
  769. if (result.reload) {
  770. payEvent.reloadPays(result.reload);
  771. } else {
  772. const refreshData = payTree.loadPostData(result);
  773. payEvent.refreshTree(refreshData);
  774. }
  775. }, function () {
  776. SpreadJsObj.reLoadRowData(sheet, sel.row, sel.rowCount);
  777. });
  778. },
  779. baseOpr: function(type) {
  780. const self = this;
  781. const node = SpreadJsObj.getSelectObject(sheet);
  782. if (type === 'delete') {
  783. postData('update', { postType: 'delete', postData: { id: node.tree_id }}, function(result) {
  784. payEvent.reloadPays(result.reload);
  785. });
  786. } else {
  787. postData('update', { postType: type, postData: { id: node.tree_id }}, function (result) {
  788. const refreshData = payTree.loadPostData(result);
  789. payEvent.refreshTree(refreshData);
  790. const sel = sheet.getSelections()[0];
  791. if (sel) {
  792. if (['up-move', 'down-move'].indexOf(type) > -1) {
  793. sheet.setSelection(payTree.getNodeIndex(node), sel.col, sel.rowCount, sel.colCount);
  794. SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, payTree.getNodeIndex(node)]);
  795. } else if (type === 'add') {
  796. sheet.setSelection(payTree.getNodeIndex(refreshData.create[0]), sel.col, sel.rowCount, sel.colCount);
  797. SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, payTree.getNodeIndex(refreshData.create[0])]);
  798. }
  799. }
  800. self.refreshActn(sheet);
  801. });
  802. }
  803. },
  804. calculateAll: function() {
  805. postData('update', { postType: 'calc', postData: {}}, function (result) {
  806. payEvent.reloadPays(result.reload);
  807. });
  808. },
  809. reloadCalcBase: function() {
  810. postData('update', { postType: 'refreshBase', postData: {}}, function (result) {
  811. payEvent.reloadPays(result.reload);
  812. payCalc.reloadBase(result.calcBase, result.addBase);
  813. });
  814. },
  815. reloadPays: function(datas){
  816. payTree.loadDatas(datas);
  817. SpreadJsObj.loadSheetData(sheet, SpreadJsObj.DataType.Tree, payTree);
  818. payEvent.refreshActn();
  819. },
  820. };
  821. spread.bind(spreadNS.Events.SelectionChanged, payEvent.selectionChanged);
  822. if (!readOnly) {
  823. spread.bind(spreadNS.Events.EditStarting, payEvent.editStarting);
  824. spread.bind(spreadNS.Events.EditEnded, payEvent.editEnded);
  825. spread.bind(spreadNS.Events.ButtonClicked, payEvent.buttonClicked);
  826. SpreadJsObj.addDeleteBind(spread, payEvent.deletePress);
  827. $('a[name="base-opr"]').click(function () {
  828. payEvent.baseOpr(this.getAttribute('type'));
  829. });
  830. $('#pay-expr').bind('change onblur', function () {
  831. if (this.readOnly) return;
  832. const expr = $(this);
  833. const row = expr.attr('data-row') ? _.toInteger(expr.attr('data-row')) : -1;
  834. const select = payTree.nodes[row];
  835. const field = expr.attr('field'), orgValue = expr.attr('org'), newValue = expr.val();
  836. if (orgValue === newValue || (!orgValue && newValue == '')) { return; }
  837. const data = { postType: 'update' };
  838. if (field === 'expr') {
  839. data.postData = { id: select.id, tp: 0, expr: newValue };
  840. const [valid, msg] = payUtils.check.isSf(select)
  841. ? payCalc.checkSfExpr(newValue, data.postData, select, payTree)
  842. : payCalc.checkExpr(newValue, data.postData, select, payTree);
  843. if (!valid) {
  844. toastr.warning(msg);
  845. this.value = select.expr;
  846. return;
  847. }
  848. } else if (field === 'start_expr') {
  849. data.updateData = {id: select.id};
  850. const [valid, msg] = payCalc.checkStartExpr(select, newValue, data.postData);
  851. if (!valid) {
  852. toastr.warning(msg);
  853. this.value = select.start_expr;
  854. return;
  855. }
  856. } else if (field === 'range_expr') {
  857. data.updateData = {id: select.id};
  858. const [valid, msg] = payCalc.checkRangeExpr(select, newValue, data.postData);
  859. if (!valid) {
  860. toastr.warning(msg);
  861. this.value = select.range_expr;
  862. return;
  863. }
  864. } else {
  865. expr.val('');
  866. return;
  867. }
  868. // 更新至服务器
  869. postData('update', data, function (result) {
  870. if (result.reload) {
  871. payEvent.reloadPays(result.reload);
  872. } else {
  873. const refreshData = payTree.loadPostData(result);
  874. payEvent.refreshTree(refreshData);
  875. }
  876. });
  877. });
  878. $('#calc-all').click(function() {
  879. payEvent.calculateAll();
  880. });
  881. $('#reload-calc-base').click(function() {
  882. payEvent.reloadCalcBase();
  883. });
  884. const deadlineObj = {
  885. payNode: null,
  886. refreshHint: function() {
  887. const dlType = $('[name=dl-type]:checked').val();
  888. const dt = deadlineType[dlType];
  889. if (dlType && dt) {
  890. const dlValue = $('#dl-value').val();
  891. $('#range-hint').text(`当 ${dt.name} >= ${dlValue} 时 `);
  892. $('#dl-hint').show();
  893. } else {
  894. $('#dl-hint').hide();
  895. }
  896. },
  897. initView: function(data) {
  898. this.payNode = data;
  899. $('#dl-pay-name').html(data.name);
  900. // 模式
  901. if (data.dl_type) {
  902. $('[name=dl-type][value=' + data.dl_type +']')[0].checked = true;
  903. } else {
  904. $('#dl-type-none')[0].checked = true;
  905. }
  906. $('#dl-value').val(data.dl_value);
  907. this.refreshHint();
  908. },
  909. getDlCount: function() {
  910. try {
  911. const result = parseInt($('#dl-value').val());
  912. if (result <= 0) throw '限制值请输入正整数';
  913. return result;
  914. } catch (err) {
  915. toastr.warning('限制值请输入正整数');
  916. return 0;
  917. }
  918. },
  919. getDlTp: function() {
  920. try {
  921. const result = parseFloat($('#dl-value').val());
  922. return result;
  923. } catch (err) {
  924. toastr.warning('限制值请输入数值');
  925. return 0;
  926. }
  927. },
  928. getUpdateData: function() {
  929. const result = { postType: 'update', postData: { id: this.payNode.id } };
  930. result.postData.dl_type = $('[name=dl-type]:checked').val();
  931. if (result.postData.dl_type) {
  932. if (result.postData.dl_type === deadlineType.phaseCount.key) {
  933. result.postData.dl_value = this.getDlCount();
  934. if (result.postData.dl_value < phasePay.phase_order) {
  935. toastr.warning(`已计量至第${phasePay.phase_order}期,计提期限不可小于该期`);
  936. return null;
  937. }
  938. } else if (result.postData.dl_type === deadlineType.stageCount.key) {
  939. result.postData.dl_value = this.getDlCount();
  940. if (result.postData.dl_value < maxStageOrder) {
  941. toastr.warning(`已计量至第${maxStageOrder}期,计提期限不可小于该期`);
  942. return null;
  943. }
  944. } else {
  945. result.postData.dl_value = this.getDlTp();
  946. const dt = deadlineType[result.postData.dl_type];
  947. if (!dt) {
  948. toastr.warning('限制模式错误,请刷新页面重试');
  949. return null;
  950. }
  951. const compareValue = payCalc.addBase[`pre_${dt.key}_tp`];
  952. if (result.postData.dl_type < compareValue) {
  953. toastr.warning(`截止上期,${dt.name}已计量${compareValue},计提期限不可小于该值`);
  954. return null;
  955. }
  956. }
  957. } else {
  958. result.postData.dl_value = 0;
  959. }
  960. return result;
  961. },
  962. };
  963. $('[name=dl-type]').change(deadlineObj.refreshHint);
  964. $('#dl-value').change(deadlineObj.refreshHint);
  965. $('#deadline-ok').click(function() {
  966. const updateData = deadlineObj.getUpdateData();
  967. if (!updateData) return;
  968. postData('update', updateData, function(result) {
  969. payEvent.reloadPays(result.reload);
  970. $('#deadline').modal('hide');
  971. });
  972. });
  973. // 右键菜单
  974. $.contextMenu({
  975. selector: '#pay-spread',
  976. build: function ($trigger, e) {
  977. const target = SpreadJsObj.safeRightClickSelection($trigger, e, spread);
  978. return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
  979. },
  980. items: {
  981. 'start': {
  982. name: '启用',
  983. icon: 'fa-play',
  984. callback: function (key, opt) {
  985. const select = SpreadJsObj.getSelectObject(sheet);
  986. const data = {
  987. postType: 'update',
  988. postData: { id: select.id, is_pause: 0 }
  989. };
  990. // 更新至服务器
  991. postData('update', data, function (result) {
  992. payEvent.reloadPays(result.reload);
  993. });
  994. },
  995. visible: function (key, opt) {
  996. const select = SpreadJsObj.getSelectObject(sheet);
  997. return (!select.children || select.children.length ===0) && !readOnly && select.is_pause && payUtils.menuVisible.pause(select);
  998. }
  999. },
  1000. 'stop': {
  1001. name: '停用',
  1002. icon: 'fa-pause',
  1003. callback: function (key, opt) {
  1004. const select = SpreadJsObj.getSelectObject(sheet);
  1005. const data = {
  1006. postType: 'update',
  1007. postData: { id: select.id, is_pause: 1 }
  1008. };
  1009. // 更新至服务器
  1010. postData('update', data, function (result) {
  1011. payEvent.reloadPays(result.reload);
  1012. });
  1013. },
  1014. visible: function (key, opt) {
  1015. const select = SpreadJsObj.getSelectObject(sheet);
  1016. return (!select.children || select.children.length === 0) && !readOnly && !select.is_pause && payUtils.menuVisible.pause(select);
  1017. },
  1018. },
  1019. 'setDeadline': {
  1020. name: '设置计提期限',
  1021. icon: 'fa-clipboard',
  1022. callback: function (key, opt) {
  1023. const select = SpreadJsObj.getSelectObject(sheet);
  1024. if (select.range_tp) {
  1025. deadlineObj.initView(select);
  1026. $('#deadline').modal('show');
  1027. } else {
  1028. toastr.warning('计提期限用于达到条件时,即刻计量至付(扣)款限额,应先设置付(扣)款限额');
  1029. }
  1030. },
  1031. visible: function (key, opt) {
  1032. const select = SpreadJsObj.getSelectObject(sheet);
  1033. return (!select.children || select.children.length === 0) && !readOnly && payUtils.menuVisible.deadline(select);
  1034. }
  1035. },
  1036. }
  1037. });
  1038. }
  1039. return { spread, sheet, payTree, loadDatas: payEvent.reloadPays }
  1040. })();
  1041. payObj.loadDatas(details);
  1042. const payFile = $.ledger_att({
  1043. selector: '#fujian',
  1044. key: 'uuid',
  1045. masterKey: 'rela_id',
  1046. uploadUrl: 'file/upload',
  1047. deleteUrl: 'file/delete',
  1048. checked: false,
  1049. zipName: `附件.zip`,
  1050. readOnly: false,
  1051. fileIdType: 'string',
  1052. fileInfo: {
  1053. user_name: 'user_name',
  1054. user_id: 'user_id',
  1055. create_time: 'create_time',
  1056. },
  1057. getCurHint: function(node) {
  1058. return`${node.name || ''}`;
  1059. },
  1060. locate: function (att) {
  1061. if (!att) return;
  1062. SpreadJsObj.locateTreeNode(payObj.sheet, att.node.tree_id, true);
  1063. payFile.getCurAttHtml(att.node);
  1064. }
  1065. });
  1066. // 展开收起标准清单
  1067. $('a', '#side-menu').bind('click', function (e) {
  1068. e.preventDefault();
  1069. const tab = $(this), tabPanel = $(tab.attr('content'));
  1070. // 展开工具栏、切换标签
  1071. if (!tab.hasClass('active')) {
  1072. // const close = $('.active', '#side-menu').length === 0;
  1073. $('a', '#side-menu').removeClass('active');
  1074. $('.tab-content .tab-select-show.tab-pane.active').removeClass('active');
  1075. tab.addClass('active');
  1076. tabPanel.addClass('active');
  1077. // $('.tab-content .tab-pane').removeClass('active');
  1078. showSideTools(tab.hasClass('active'));
  1079. } else { // 收起工具栏
  1080. tab.removeClass('active');
  1081. tabPanel.removeClass('active');
  1082. showSideTools(tab.hasClass('active'));
  1083. }
  1084. payObj.spread.refresh();
  1085. });
  1086. postData('load', {filter: 'file'}, function(result) {
  1087. for (const f of result.file) {
  1088. f.node = payObj.payTree.datas.find(x => { return x.uuid === f.rela_id; });
  1089. }
  1090. payFile.loadDatas(result.file);
  1091. payFile.getCurAttHtml(SpreadJsObj.getSelectObject(payObj.sheet));
  1092. });
  1093. // 工具栏spr
  1094. $.divResizer({
  1095. select: '#right-spr',
  1096. callback: function () {
  1097. payObj.spread.refresh();
  1098. }
  1099. });
  1100. // todo 加载审批列表
  1101. $.subMenu({
  1102. menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
  1103. toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
  1104. key: 'menu.1.0.0',
  1105. miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
  1106. callback: function (info) {
  1107. if (info.mini) {
  1108. $('.panel-title').addClass('fluid');
  1109. $('#sub-menu').removeClass('panel-sidebar');
  1110. } else {
  1111. $('.panel-title').removeClass('fluid');
  1112. $('#sub-menu').addClass('panel-sidebar');
  1113. }
  1114. autoFlashHeight();
  1115. payObj.spread.refresh();
  1116. }
  1117. });
  1118. });