se_bonus.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. 'use strict';
  2. /**
  3. * 奖罚金
  4. *
  5. * @author Mai
  6. * @date 2020/2/12
  7. * @version
  8. */
  9. const isPre = function (data) {
  10. return data && data.sid !== stageId;
  11. };
  12. $(document).ready(() => {
  13. autoFlashHeight();
  14. const fileObj = {
  15. generateFilesHtml(data) {
  16. const id = data.id, files = data.proof_file;
  17. let html = [];
  18. if (files !== null && files !== undefined) {
  19. for (const [i, f] of files.entries()) {
  20. html.push('<tr>');
  21. html.push('<td style="width: 200px">', f.filename + f.fileext, '</td>');
  22. html.push('<td>', f.username, '</td>');
  23. html.push('<td>', f.in_time, '</td>');
  24. html.push('<td>');
  25. // 下载
  26. html.push('<a href="' + window.location.pathname + '/file/download?id=' + id + '&index=' + i + ' title="下载><i class="fa fa-download "></i></a>');
  27. // 删除
  28. if (!readOnly && uploadPermission && !isPre(data)) {
  29. html.push('<a class="delete-att text-danger" href="javascript:void(0);" data-id ="' + id + '"file-index="' + i + '" title="删除"><i class="fa fa-remove "></i></a>');
  30. }
  31. html.push('</td>');
  32. html.push('</tr>');
  33. }
  34. }
  35. $('#file-list').html(html.join(''));
  36. },
  37. };
  38. let datepicker;
  39. const spreadSetting = {
  40. cols: [
  41. {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 235, formatter: '@', readOnly: isPre, },
  42. {title: '金额', colSpan: '1', rowSpan: '1', field: 'tp', hAlign: 2, width: 100, type: 'Number', readOnly: isPre, },
  43. {
  44. title: '时间', colSpan: '1', rowSpan: '1', field: 'real_time', hAlign: 2, width: 150, readOnly: true,
  45. formatter: 'yyyy-MM-dd', cellType: 'activeImageBtn', normalImg: '#ellipsis-icon', indent: 5,
  46. showImage: function (data) {
  47. return data !== undefined && data !== null;
  48. },
  49. },
  50. {title: '编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 150, formatter: '@', readOnly: isPre, },
  51. {title: '发文单位', colSpan: '1', rowSpan: '1', field: 'doc_co', hAlign: 0, width: 150, formatter: '@', readOnly: isPre},
  52. // {
  53. // title: '依据材料证明', colSpan: '1', rowSpan: '1', field: 'proof_file', hAlign: 1, width: 80, formatter: '@',
  54. // readOnly: true, cellType: 'imageBtn', normalImg: '#rela-file-icon', hoverImg: '#rela-file-hover',
  55. // getValue: function (data) {
  56. // return data.proof_file ? data.proof_file.length : 0;
  57. // },
  58. // showImage: function (data) {
  59. // return data !== undefined && data !== null;
  60. // },
  61. // },
  62. {title: '依据材料证明', colSpan: '1', rowSpan: '1', field: 'proof', hAlign: 0, width: 150, formatter: '@', readOnly: isPre},
  63. {
  64. title: '计量期', colSpan: '1', rowSpan: '1', field: 'sorder', hAlign: 1, width: 100, formatter: '@',
  65. getValue: function (data) {
  66. return '第' + data.sorder + '期';
  67. }, readOnly: true,
  68. },
  69. {title: '备注', colSpan: '1', rowSpan: '1', field: 'memo', hAlign: 0, width: 180, formatter: '@', cellType: 'ellipsisAutoTip', readOnly: isPre, }
  70. ],
  71. emptyRows: readOnly ? 0 : 3,
  72. headRows: 1,
  73. headRowHeight: [32],
  74. defaultRowHeight: 21,
  75. headerFont: '12px 微软雅黑',
  76. font: '12px 微软雅黑',
  77. readOnly: readOnly,
  78. imageClick: function (data, hitinfo) {
  79. if (!data || readOnly) return;
  80. const setting = hitinfo.sheet.zh_setting;
  81. if (!setting) return;
  82. const col = setting.cols[hitinfo.col];
  83. if (!col) return;
  84. if (col.field === 'proof_file') {
  85. fileObj.generateFilesHtml(data);
  86. $('#file').modal('show');
  87. }
  88. if (col.field === 'real_time') {
  89. const pos = SpreadJsObj.getObjPos(hitinfo.sheet.getParent().qo);
  90. if (!datepicker) {
  91. datepicker = $('.datepicker-here').datepicker({
  92. language: 'zh',
  93. dateFormat: 'yyyy-MM-dd',
  94. autoClose: true,
  95. onSelect: function (formattedDate, date, inst) {
  96. if (!inst.visible) return;
  97. const sels = hitinfo.sheet.getSelections();
  98. if (!sels || !sels[0]) return;
  99. const node = SpreadJsObj.getSelectObject(hitinfo.sheet);
  100. const uData = { update: {id: node.id, real_time: date} };
  101. postData(window.location.pathname + '/update', uData, function (result) {
  102. bonusObj.loadUpdateData(result);
  103. SpreadJsObj.reLoadRowData(hitinfo.sheet, sels[0].row);
  104. }, function () {
  105. SpreadJsObj.reLoadRowData(hitinfo.sheet, sels[0].row);
  106. });
  107. }
  108. }).data('datepicker');
  109. }
  110. const value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
  111. if (value) {
  112. datepicker.selectDate(value);
  113. } else {
  114. datepicker.clear();
  115. }
  116. datepicker.show();
  117. $('#datepickers-container').css('top', hitinfo.cellRect.y + pos.y).css('left', hitinfo.cellRect.x + pos.x);
  118. }
  119. }
  120. };
  121. const bonusSpread = SpreadJsObj.createNewSpread($('#bonus-spread')[0]);
  122. const bonusSheet = bonusSpread.getActiveSheet();
  123. spreadSetting.readOnly = readOnly;
  124. SpreadJsObj.initSheet(bonusSheet, spreadSetting);
  125. $.subMenu({
  126. menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
  127. toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
  128. key: 'menu.1.0.0',
  129. miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
  130. callback: function (info) {
  131. if (info.mini) {
  132. $('.panel-title').addClass('fluid');
  133. $('#sub-menu').removeClass('panel-sidebar');
  134. } else {
  135. $('.panel-title').removeClass('fluid');
  136. $('#sub-menu').addClass('panel-sidebar');
  137. }
  138. autoFlashHeight();
  139. bonusSpread.refresh();
  140. }
  141. });
  142. class Bonus {
  143. constructor () {
  144. this.data = [];
  145. }
  146. resortData() {
  147. this.data.sort(function (a, b) {
  148. return a.sorder !== b.sorder ? a.sorder - b.sorder : a.order - b.order;
  149. });
  150. }
  151. loadDatas(datas) {
  152. this.data = datas;
  153. this.resortData();
  154. }
  155. loadUpdateData(updateData) {
  156. if (updateData.add) {
  157. for (const a of updateData.add) {
  158. this.data.push(a);
  159. }
  160. }
  161. if (updateData.update) {
  162. for (const u of updateData.update) {
  163. const d = this.data.find(function (x) {
  164. return u.id === x.id;
  165. });
  166. if (d) {
  167. _.assign(d, u);
  168. } else {
  169. this.data.push(d);
  170. }
  171. }
  172. }
  173. if (updateData.del) {
  174. _.remove(this.data, function (d) {
  175. return updateData.del.indexOf(d.id) >= 0;
  176. });
  177. }
  178. this.resortData();
  179. }
  180. getCurStageNewOrder() {
  181. const cur = this.data.filter(function (x) {
  182. return x.sid === stageId;
  183. });
  184. return cur && cur.length > 0 ? cur.length + 1 : 1;
  185. }
  186. checkCurFirst(bonusData) {
  187. const cur = this.data.filter(function (x) {
  188. return x.sid === stageId;
  189. });
  190. return cur.indexOf(bonusData) === 0;
  191. }
  192. checkCurLast(bonusData) {
  193. const cur = this.data.filter(function (x) {
  194. return x.sid === stageId;
  195. });
  196. return cur.indexOf(bonusData) === cur.length - 1;
  197. }
  198. }
  199. const bonusObj = new Bonus();
  200. postData(window.location.pathname + '/load', null, function (result) {
  201. bonusObj.loadDatas(result);
  202. SpreadJsObj.loadSheetData(bonusSheet, SpreadJsObj.DataType.Data, bonusObj.data);
  203. });
  204. if (!readOnly) {
  205. const bonusOprObj = {
  206. /**
  207. * 删除按钮响应事件
  208. * @param sheet
  209. */
  210. deletePress: function (sheet) {
  211. if (!sheet.zh_setting || readOnly) return;
  212. const sortData = sheet.zh_data;
  213. const datas = [];
  214. const sels = sheet.getSelections();
  215. if (!sels || !sels[0]) return;
  216. const hint = {
  217. name: {type: 'warning', msg: '名称不能为空,如需删除甲供材料请使用右键删除'},
  218. };
  219. for (let iRow = sels[0].row; iRow < sels[0].row + sels[0].rowCount; iRow++) {
  220. let bDel = false;
  221. const node = sortData[iRow];
  222. if (node) {
  223. const data = {id: node.id};
  224. for (let iCol = sels[0].col; iCol < sels[0].col + sels[0].colCount; iCol++) {
  225. const colSetting = sheet.zh_setting.cols[iCol];
  226. if (colSetting.field === 'name') {
  227. toastMessageUniq(hint.name);
  228. return;
  229. }
  230. const style = sheet.getStyle(iRow, iCol);
  231. if (!style.locked) {
  232. const colSetting = sheet.zh_setting.cols[iCol];
  233. data[colSetting.field] = null;
  234. bDel = true;
  235. }
  236. }
  237. if (bDel) {
  238. datas.push(data);
  239. }
  240. }
  241. }
  242. if (datas.length > 0) {
  243. postData(window.location.pathname + '/update', {update: datas}, function (result) {
  244. bonusObj.loadUpdateData(result);
  245. SpreadJsObj.reLoadSheetData(bonusSheet);
  246. }, function () {
  247. SpreadJsObj.reLoadSheetData(bonusSheet);
  248. });
  249. }
  250. },
  251. delete: function () {
  252. const sheet = bonusSheet;
  253. if (!sheet.zh_setting || readOnly) return;
  254. const sortData = sheet.zh_data;
  255. const datas = [];
  256. const sels = sheet.getSelections();
  257. if (!sels || !sels[0]) return;
  258. const hint = {
  259. isOld: {type: 'warning', msg: '本项为往期数据,不可删除'},
  260. invalidDel: {type: 'warning', msg: '本项不是您新增的,只有原报和新增人可删除'},
  261. };
  262. for (let iRow = sels[0].row, iLen = sels[0].row + sels[0].rowCount; iRow < iLen; iRow++) {
  263. const node = sortData[iRow];
  264. if (node.sid !== stageId) {
  265. toastMessageUniq(hint.isOld);
  266. continue;
  267. } else {
  268. if (node.uid !== userID && stageUserId !== userID) {
  269. toastMessageUniq(hint.invalidDel);
  270. continue;
  271. }
  272. datas.push(node.id);
  273. }
  274. }
  275. if (datas.length > 0) {
  276. postData(window.location.pathname + '/update', {del: datas}, function (result) {
  277. bonusObj.loadUpdateData(result);
  278. SpreadJsObj.reLoadSheetData(sheet);
  279. }, function () {
  280. SpreadJsObj.reLoadSheetData(sheet);
  281. });
  282. }
  283. },
  284. editEnded: function (e, info) {
  285. if (!info.sheet.zh_setting || !info.sheet.zh_data) return;
  286. const node = info.sheet.zh_data[info.row];
  287. const col = info.sheet.zh_setting.cols[info.col];
  288. const data = {};
  289. if (node) {
  290. data.update = {};
  291. data.update.id = node.id;
  292. const oldValue = node ? node[col.field] : null;
  293. const newValue = trimInvalidChar(info.editingText);
  294. if (oldValue == info.editingText || ((!oldValue || oldValue === '') && (newValue === ''))) {
  295. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  296. return;
  297. }
  298. data.update[col.field] = newValue;
  299. } else {
  300. if (col.field !== 'name') {
  301. toastr.warning('新增奖罚金,请先输入名称');
  302. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  303. return;
  304. }
  305. data.add = {};
  306. data.add.order = bonusObj.getCurStageNewOrder();
  307. data.add.name = trimInvalidChar(info.editingText);
  308. }
  309. postData(window.location.pathname + '/update', data, function (result) {
  310. bonusObj.loadUpdateData(result);
  311. SpreadJsObj.reLoadSheetData(info.sheet);
  312. }, function () {
  313. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  314. });
  315. },
  316. clipboardPasting(e, info) {
  317. const setting = info.sheet.zh_setting, sortData = info.sheet.zh_data;
  318. info.cancel = true;
  319. if (!setting || !sortData) return;
  320. const pasteData = info.pasteData.html
  321. ? SpreadJsObj.analysisPasteHtml(info.pasteData.html)
  322. : (info.pasteData.text === ''
  323. ? SpreadJsObj.Clipboard.getAnalysisPasteText()
  324. : SpreadJsObj.analysisPasteText(info.pasteData.text));
  325. const hint = {
  326. name: {type: 'warning', msg: '奖罚金名称不可为空,已过滤'},
  327. tp: {type: 'warning', msg: '输入的 金额 非法,已过滤'},
  328. };
  329. const uDatas = [], iDatas = [], maxOrder = bonusObj.getCurStageNewOrder();
  330. for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
  331. const curRow = info.cellRange.row + iRow;
  332. const node = sortData[curRow];
  333. let bPaste = false;
  334. const data = {};
  335. for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
  336. const curCol = info.cellRange.col + iCol;
  337. const colSetting = setting.cols[curCol];
  338. const value = trimInvalidChar(pasteData[iRow][iCol]);
  339. if (colSetting.field === 'name' && (!value || value === '')) {
  340. toastMessageUniq(hint.name);
  341. break;
  342. }
  343. if (colSetting.type === 'Number') {
  344. const num = _.toNumber(value);
  345. if (num) {
  346. data[colSetting.field] = num;
  347. bPaste = true;
  348. }
  349. } else {
  350. data[colSetting.field] = value;
  351. bPaste = true;
  352. }
  353. }
  354. if (bPaste) {
  355. if (node) {
  356. data.id = node.id;
  357. uDatas.push(data);
  358. } else {
  359. data.order = maxOrder + iRow;
  360. iDatas.push(data);
  361. }
  362. }
  363. }
  364. const updateData = {};
  365. if (uDatas.length > 0) updateData.update = uDatas;
  366. if (iDatas.length > 0) updateData.add = iDatas;
  367. if (uDatas.length > 0 || iDatas.length > 0) {
  368. postData(window.location.pathname + '/update', updateData, function (result) {
  369. bonusObj.loadUpdateData(result);
  370. SpreadJsObj.reLoadSheetData(info.sheet);
  371. });
  372. } else {
  373. SpreadJsObj.reLoadSheetData(info.sheet);
  374. }
  375. },
  376. upMove: function () {
  377. const sheet = bonusSheet;
  378. const sels = sheet.getSelections(), sortData = sheet.zh_data;
  379. const node = sortData[sels[0].row];
  380. const preNode = sortData[sels[0].row - 1];
  381. const data = [
  382. {id: node.id, order: preNode.order},
  383. {id: preNode.id, order: node.order}
  384. ];
  385. postData(window.location.pathname + '/update', {update: data}, function (result) {
  386. bonusObj.loadUpdateData(result);
  387. SpreadJsObj.reLoadRowsData(sheet, [sels[0].row, sels[0].row - 1]);
  388. sheet.setSelection(sels[0].row - 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
  389. });
  390. },
  391. downMove: function () {
  392. const sheet = bonusSheet;
  393. const sels = sheet.getSelections(), sortData = sheet.zh_data;
  394. const node = sortData[sels[0].row];
  395. const nextNode = sortData[sels[0].row + 1];
  396. const data = [
  397. {id: node.id, order: nextNode.order},
  398. {id: nextNode.id, order: node.order}
  399. ];
  400. postData(window.location.pathname + '/update', {update: data}, function (result) {
  401. bonusObj.loadUpdateData(result);
  402. SpreadJsObj.reLoadRowsData(sheet, [sels[0].row, sels[0].row + 1]);
  403. sheet.setSelection(sels[0].row + 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
  404. });
  405. }
  406. };
  407. bonusSheet.bind(spreadNS.Events.EditEnded, bonusOprObj.editEnded);
  408. bonusSheet.bind(spreadNS.Events.ClipboardPasting, bonusOprObj.clipboardPasting);
  409. SpreadJsObj.addDeleteBind(bonusSpread, bonusOprObj.deletePress);
  410. $.contextMenu({
  411. selector: '#bonus-spread',
  412. build: function ($trigger, e) {
  413. const target = SpreadJsObj.safeRightClickSelection($trigger, e, bonusSpread);
  414. return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
  415. },
  416. items: {
  417. del: {
  418. name: '删除',
  419. icon: 'fa-remove',
  420. callback: function (key, opt) {
  421. bonusOprObj.delete();
  422. },
  423. disabled: function (key, opt) {
  424. const sels = bonusSheet.getSelections();
  425. if (!sels || !sels[0]) return true;
  426. const row = sels[0].row;
  427. const node = bonusObj.data[row];
  428. return node === undefined || node === null || node.sid !== stageId;
  429. },
  430. visible: function (key, opt) {
  431. return !readOnly;
  432. }
  433. },
  434. sprDel: '------------',
  435. upMove: {
  436. name: '上移',
  437. icon: 'fa-arrow-up',
  438. callback: function (key, opt) {
  439. bonusOprObj.upMove();
  440. },
  441. disabled: function (key, opt) {
  442. const sels = bonusSheet.getSelections();
  443. if (!sels || !sels[0] || sels[0].row === 0) return true;
  444. const row = sels[0].row;
  445. const node = bonusObj.data[row];
  446. return node === undefined || node === null || node.sid !== stageId || bonusObj.checkCurFirst(node);
  447. },
  448. visible: function (key, opt) {
  449. return !readOnly;
  450. }
  451. },
  452. downMove: {
  453. name: '下移',
  454. icon: 'fa-arrow-down',
  455. callback: function (key, opt) {
  456. bonusOprObj.downMove();
  457. },
  458. disabled: function (key, opt) {
  459. const sels = bonusSheet.getSelections();
  460. if (!sels || !sels[0] || sels[0].row >= bonusObj.data.length - 1) return true;
  461. const row = sels[0].row;
  462. const node = bonusObj.data[row];
  463. return node === undefined || node === null || node.sid !== stageId || bonusObj.checkCurLast(node);
  464. },
  465. visible: function (key, opt) {
  466. return !readOnly;
  467. }
  468. }
  469. },
  470. });
  471. }
  472. });