payment_safe.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. function getTenderId() {
  2. return window.location.pathname.split('/')[2];
  3. }
  4. const invalidFields = {
  5. parent: ['cur_qty', 'cur_tp', 'unit_price'],
  6. };
  7. $(document).ready(function() {
  8. let stdGcl;
  9. autoFlashHeight();
  10. class BillsObj {
  11. constructor() {
  12. this.spread = SpreadJsObj.createNewSpread($('#bills-spread')[0]);
  13. this.sheet = this.spread.getActiveSheet();
  14. this.treeSetting = {
  15. id: 'tree_id',
  16. pid: 'tree_pid',
  17. order: 'tree_order',
  18. level: 'tree_level',
  19. isLeaf: 'tree_is_leaf',
  20. fullPath: 'tree_full_path',
  21. rootId: -1,
  22. calcFields: ['cur_tp', 'pre_tp', 'end_tp'],
  23. keys: ['id', 'detail_id', 'tree_id'],
  24. };
  25. this.tree = createNewPathTree('ledger', this.treeSetting);
  26. this.spreadSetting = {
  27. cols: [
  28. {title: '编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 230, formatter: '@', cellType: 'tree'},
  29. {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@'},
  30. {title: '规格', colSpan: '1', rowSpan: '2', field: 'spec', hAlign: 0, width: 150, formatter: '@'},
  31. {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'},
  32. {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number'},
  33. {title: '本期|数量', colSpan: '2|1', rowSpan: '1|1', field: 'cur_qty', hAlign: 2, width: 60, type: 'Number'},
  34. {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'cur_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
  35. {title: '截止本期|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qty', hAlign: 2, width: 60, type: 'Number'},
  36. {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
  37. {title: '发票号', colSpan: '1', rowSpan: '2', field: 'invoice_code', hAlign: 0, width: 80, formatter: '@'},
  38. {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
  39. ],
  40. emptyRows: 3,
  41. headRows: 2,
  42. headRowHeight: [25, 25],
  43. defaultRowHeight: 21,
  44. headerFont: '12px 微软雅黑',
  45. font: '12px 微软雅黑',
  46. readOnly: readOnly,
  47. };
  48. this.ckBillsSpread = window.location.pathname + '-billsSelect';
  49. this.initSpread();
  50. this.initOtherEvent();
  51. }
  52. initSpread() {
  53. SpreadJsObj.initSheet(this.sheet, this.spreadSetting);
  54. this.spread.bind(spreadNS.Events.SelectionChanged, this.selectionChanged);
  55. this.spread.bind(spreadNS.Events.topRowChanged, this.topRowChanged);
  56. this.spread.bind(spreadNS.Events.ClipboardChanging, function (e, info) {
  57. const copyText = SpreadJsObj.getFilterCopyText(info.sheet);
  58. SpreadJsObj.Clipboard.setCopyData(copyText);
  59. });
  60. if (readOnly) return;
  61. this.spread.bind(spreadNS.Events.EditEnded, this.editEnded);
  62. this.spread.bind(spreadNS.Events.EditStarting, this.editStarting);
  63. this.spread.bind(spreadNS.Events.ClipboardPasting, this.clipboardPasting);
  64. SpreadJsObj.addDeleteBind(this.spread, this.deletePress);
  65. }
  66. initOtherEvent() {
  67. const self = this;
  68. // 增删上下移升降级
  69. $('a[name="base-opr"]').click(function () {
  70. self.baseOpr(this.getAttribute('type'));
  71. });
  72. }
  73. refreshOperationValid() {
  74. const setObjEnable = function (obj, enable) {
  75. if (enable) {
  76. obj.removeClass('disabled');
  77. } else {
  78. obj.addClass('disabled');
  79. }
  80. };
  81. const invalidAll = function () {
  82. setObjEnable($('a[name=base-opr][type=add]'), false);
  83. setObjEnable($('a[name=base-opr][type=delete]'), false);
  84. setObjEnable($('a[name=base-opr][type=up-move]'), false);
  85. setObjEnable($('a[name=base-opr][type=down-move]'), false);
  86. setObjEnable($('a[name=base-opr][type=up-level]'), false);
  87. setObjEnable($('a[name=base-opr][type=down-level]'), false);
  88. };
  89. const sel = this.sheet.getSelections()[0];
  90. const row = sel ? sel.row : -1;
  91. const tree = this.sheet.zh_tree;
  92. if (!tree) {
  93. invalidAll();
  94. return;
  95. }
  96. const first = tree.nodes[row];
  97. if (!first) {
  98. invalidAll();
  99. return;
  100. }
  101. let last = first, sameParent = true, nodeUsed = this.checkNodeUsed(tree, first);
  102. if (sel.rowCount > 1 && first) {
  103. for (let r = 1; r < sel.rowCount; r++) {
  104. const rNode = tree.nodes[sel.row + r];
  105. if (!rNode) {
  106. sameParent = false;
  107. break;
  108. }
  109. nodeUsed = nodeUsed || this.checkNodeUsed(tree, rNode);
  110. if (rNode.tree_level > first.tree_level) continue;
  111. if ((rNode.tree_level < first.tree_level) || (rNode.tree_level === first.tree_level && rNode.tree_pid !== first.tree_pid)) {
  112. sameParent = false;
  113. break;
  114. }
  115. last = rNode;
  116. }
  117. }
  118. const preNode = tree.getPreSiblingNode(first);
  119. const valid = !this.sheet.zh_setting.readOnly;
  120. setObjEnable($('a[name=base-opr][type=add]'), valid && first && first.tree_level > 1);
  121. setObjEnable($('a[name=base-opr][type=delete]'), valid && first && sameParent && first.tree_level > 1 && !nodeUsed);
  122. setObjEnable($('a[name=base-opr][type=up-move]'), valid && first && sameParent && first.tree_level > 1 && preNode);
  123. setObjEnable($('a[name=base-opr][type=down-move]'), valid && first && sameParent && first.tree_level > 1 && !tree.isLastSibling(last));
  124. setObjEnable($('a[name=base-opr][type=up-level]'), valid && first && sameParent && tree.getParent(first) && !nodeUsed
  125. && first.tree_level > 2 && !tree.isLastSibling(last));
  126. setObjEnable($('a[name=base-opr][type=down-level]'), valid && first && sameParent
  127. && first.tree_level > 1 && preNode && !this.checkNodeUsed(tree, preNode));
  128. }
  129. loadRelaData() {
  130. this.refreshOperationValid();
  131. SpreadJsObj.saveTopAndSelect(this.sheet, this.ckBillsSpread);
  132. }
  133. refreshTree(data) {
  134. const sheet = this.sheet;
  135. SpreadJsObj.massOperationSheet(sheet, function () {
  136. const tree = sheet.zh_tree;
  137. // 处理删除
  138. if (data.delete) {
  139. data.delete.sort(function (a, b) {
  140. return b.deleteIndex - a.deleteIndex;
  141. });
  142. for (const d of data.delete) {
  143. sheet.deleteRows(d.deleteIndex, 1);
  144. }
  145. }
  146. // 处理新增
  147. if (data.create) {
  148. const newNodes = data.create;
  149. if (newNodes) {
  150. newNodes.sort(function (a, b) {
  151. return a.index - b.index;
  152. });
  153. for (const node of newNodes) {
  154. sheet.addRows(node.index, 1);
  155. SpreadJsObj.reLoadRowData(sheet, tree.nodes.indexOf(node), 1);
  156. }
  157. }
  158. }
  159. // 处理更新
  160. if (data.update) {
  161. const rows = [];
  162. for (const u of data.update) {
  163. rows.push(tree.nodes.indexOf(u));
  164. }
  165. SpreadJsObj.reLoadRowsData(sheet, rows);
  166. }
  167. // 处理展开
  168. if (data.expand) {
  169. const expanded = [];
  170. for (const e of data.expand) {
  171. if (expanded.indexOf(e) === -1) {
  172. const posterity = tree.getPosterity(e);
  173. for (const p of posterity) {
  174. sheet.setRowVisible(tree.nodes.indexOf(p), p.visible);
  175. expanded.push(p);
  176. }
  177. }
  178. }
  179. }
  180. });
  181. }
  182. loadData(datas) {
  183. this.tree.loadDatas(datas);
  184. treeCalc.calculateAll(this.tree);
  185. SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Tree, this.tree);
  186. SpreadJsObj.loadTopAndSelect(this.sheet, this.ckBillsSpread);
  187. this.refreshOperationValid();
  188. }
  189. getDefaultSelectInfo() {
  190. if (!this.tree) return;
  191. const sel = this.sheet.getSelections()[0];
  192. const node = this.sheet.zh_tree.nodes[sel.row];
  193. if (!node) return;
  194. let count = 1;
  195. if (sel.rowCount > 1) {
  196. for (let r = 1; r < sel.rowCount; r++) {
  197. const rNode = sheet.zh_tree.nodes[sel.row + r];
  198. if (rNode.tree_level > node.tree_level) continue;
  199. if ((rNode.tree_level < node.tree_level) || (rNode.tree_level === node.tree_level && rNode.tree_pid !== node.tree_pid)) {
  200. toastr.warning('请选择同一节点下的节点,进行该操作');
  201. return;
  202. }
  203. count += 1;
  204. }
  205. }
  206. return [this.tree, node, count];
  207. }
  208. checkNodeUsed(tree, node) {
  209. // todo 检查节点是否已使用
  210. return false;
  211. }
  212. baseOpr(type, addCount = 1) {
  213. const self = this;
  214. const sheet = self.sheet;
  215. const sel = sheet.getSelections()[0];
  216. const [tree, node, count] = this.getDefaultSelectInfo();
  217. if (!tree || !node || !count) return;
  218. if (type === 'delete') {
  219. const parent = tree.getParent(node);
  220. const children = parent ? parent.children : tree.children;
  221. const index = children.indexOf(node);
  222. for (let i = 0; i < count; i++) {
  223. const child = children[i+index];
  224. if (this.checkNodeUsed(tree, child)) {
  225. toastr.warning('选中的节点已计量,不可删除');
  226. return;
  227. }
  228. }
  229. } else if (type === 'up-level') {
  230. const parent = tree.getParent(node);
  231. const children = parent ? parent.children : tree.children;
  232. const index = children.indexOf(node);
  233. for (let i = index; i < children.length; i++) {
  234. const child = children[index];
  235. if (this.checkNodeUsed(tree, child)) {
  236. if (i >= index + count) {
  237. toastr.warning('其后节点已计量,选中的节点不可升级');
  238. } else {
  239. toastr.warning('选中的节点已计量,不可升级');
  240. }
  241. return;
  242. }
  243. }
  244. } else if (type === 'down-level') {
  245. const parent = tree.getParent(node);
  246. const children = parent ? parent.children : tree.children;
  247. const index = children.indexOf(node);
  248. if (index > 0 && this.checkNodeUsed(tree, children[index-1])) {
  249. toastr.warning('其前节点已计量,选中的节点不可降级');
  250. return;
  251. }
  252. for (let i = index; i < count; i++) {
  253. const child = children[i+index];
  254. if (this.checkNodeUsed(tree, child)) {
  255. toastr.warning('选中的节点已计量,不可降级');
  256. return;
  257. }
  258. }
  259. }
  260. const updateData = {
  261. postType: type,
  262. postData: {
  263. id: node.tree_id,
  264. count: type === 'add' ? addCount : count,
  265. }
  266. };
  267. if (type === 'delete') {
  268. deleteAfterHint(function () {
  269. postData('update', updateData, function (result) {
  270. const refreshData = tree.loadPostData(result);
  271. self.refreshTree(refreshData);
  272. if (sel) {
  273. sheet.setSelection(sel.row, sel.col, 1, sel.colCount);
  274. }
  275. self.refreshOperationValid();
  276. });
  277. });
  278. } else {
  279. postData('update', updateData, function (result) {
  280. const refreshData = tree.loadPostData(result);
  281. self.refreshTree(refreshData);
  282. if (['up-move', 'down-move'].indexOf(type) > -1) {
  283. if (sel) {
  284. sheet.setSelection(tree.nodes.indexOf(node), sel.col, sel.rowCount, sel.colCount);
  285. // SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(node)]);
  286. }
  287. } else if (type === 'add') {
  288. const sel = sheet.getSelections()[0];
  289. if (sel) {
  290. sheet.setSelection(tree.nodes.indexOf(refreshData.create[0]), sel.col, sel.rowCount, sel.colCount);
  291. // SpreadJsObj.reloadRowsBackColor(sheet, [sel.row, tree.nodes.indexOf(refreshData.create[0])]);
  292. }
  293. }
  294. self.refreshOperationValid();
  295. });
  296. }
  297. }
  298. // 事件
  299. selectionChanged(e, info) {
  300. if (info.newSelections) {
  301. if (!info.oldSelections || info.newSelections[0].row !== info.oldSelections[0].row) {
  302. billsObj.loadRelaData();
  303. }
  304. }
  305. }
  306. topRowChanged(e, info) {
  307. SpreadJsObj.saveTopAndSelect(info.sheet, billsObj.ckBillsSpread);
  308. }
  309. editEnded(e, info) {
  310. if (!info.sheet.zh_setting) return;
  311. const tree = info.sheet.zh_tree;
  312. const node = SpreadJsObj.getSelectObject(info.sheet);
  313. const data = { id: node.id, detail_id: node.detail_id, tree_id: node.tree_id };
  314. // 未改变值则不提交
  315. const col = info.sheet.zh_setting.cols[info.col];
  316. const orgValue = node[col.field];
  317. const newValue = trimInvalidChar(info.editingText);
  318. if (orgValue == info.editingText || ((!orgValue || orgValue === '') && (newValue === ''))) return;
  319. if (info.editingText) {
  320. const text = newValue;
  321. if (billsObj.checkNodeUsed(tree, node) && col.field ==='b_code' && orgValue !== '' && text === '') {
  322. toastr.error('节点已计量,请勿删除编号');
  323. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  324. return;
  325. }
  326. if (col.type === 'Number') {
  327. const num = _.toNumber(text);
  328. if (_.isFinite(num)) {
  329. data[col.field] = num;
  330. } else {
  331. try {
  332. data[col.field] = math.evaluate(transExpr(text));
  333. } catch(err) {
  334. toastr.error('输入的表达式非法');
  335. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  336. return;
  337. }
  338. }
  339. } else {
  340. data[col.field] = text;
  341. }
  342. } else {
  343. if (billsObj.checkNodeUsed(tree, node) && (col.field ==='b_code') && orgValue !== '') {
  344. toastr.error('节点已计量,请勿删除编号');
  345. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  346. return;
  347. }
  348. data[col.field] = col.type === 'Number' ? 0 : '';
  349. }
  350. // 更新至服务器
  351. postData('update', {postType: 'update', postData: data}, function (result) {
  352. const refreshNode = billsObj.tree.loadPostData(result);
  353. billsObj.refreshTree(refreshNode);
  354. }, function () {
  355. SpreadJsObj.reLoadRowData(info.sheet, info.row, 1);
  356. });
  357. }
  358. editStarting(e, info) {
  359. if (!info.sheet.zh_setting || !info.sheet.zh_tree) return;
  360. const tree = info.sheet.zh_tree;
  361. const col = info.sheet.zh_setting.cols[info.col];
  362. const node = info.sheet.zh_tree.nodes[info.row];
  363. if (!node) {
  364. info.cancel = true;
  365. return;
  366. }
  367. switch (col.field) {
  368. case 'b_code':
  369. info.cancel = readOnly || billsObj.checkNodeUsed(tree, node);
  370. break;
  371. case 'unit_price':
  372. info.cancel = readOnly || (node.children && node.children.length > 0) || billsObj.checkNodeUsed(tree, node);
  373. break;
  374. case 'cur_qty':
  375. case 'cur_tp':
  376. info.cancel = (node.children && node.children.length > 0);
  377. break;
  378. }
  379. }
  380. deletePress (sheet) {
  381. if (!sheet.zh_setting) return;
  382. const sel = sheet.getSelections()[0], datas = [];
  383. for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow++) {
  384. let bDel = false;
  385. const node = sheet.zh_tree.nodes[iRow];
  386. const data = sheet.zh_tree.getNodeKeyData(node);
  387. for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
  388. const col = sheet.zh_setting.cols[iCol];
  389. const style = sheet.getStyle(iRow, iCol);
  390. if (style.locked) continue;
  391. if (col.field === 'b_code' && sheet.zh_tree.checkNodeUsed(node, pos)) {
  392. toastr.warning(`"${node.b_code || ''} ${node.name}"已计量,请勿修改`);
  393. return;
  394. }
  395. data[col.field] = col.type === 'Number' ? 0 : '';
  396. bDel = true;
  397. }
  398. if (bDel) datas.push(data);
  399. }
  400. if (datas.length > 0) {
  401. postData('update', {postType: 'update', postData: datas}, function (result) {
  402. const refreshNode = sheet.zh_tree.loadPostData(result);
  403. billsObj.refreshTree(refreshNode);
  404. }, function () {
  405. SpreadJsObj.reLoadRowData(info.sheet, sel.row, sel.rowCount);
  406. });
  407. }
  408. }
  409. clipboardPasting(e, info) {
  410. info.cancel = true;
  411. const tree = info.sheet.zh_tree, setting = info.sheet.zh_setting;
  412. if (!setting || !tree) return;
  413. const pasteData = info.pasteData.html
  414. ? SpreadJsObj.analysisPasteHtml(info.pasteData.html)
  415. : (info.pasteData.text === ''
  416. ? SpreadJsObj.Clipboard.getAnalysisPasteText()
  417. : SpreadJsObj.analysisPasteText(info.pasteData.text));
  418. const hint = {
  419. usedUp: {type: 'warning', msg: '节点已计量,不可修改单价'},
  420. usedCode: {type: 'warning', msg: '节点已计量,编号不可修改'},
  421. invalidExpr: {type: 'warning', msg: '粘贴的表达式非法'},
  422. parent: {type: 'warning', msg: '含有子项的清单,不可粘贴数量、单价、金额'},
  423. };
  424. const datas = [], filterNodes = [];
  425. let level, filterRow = 0;
  426. for (let iRow = 0; iRow < info.cellRange.rowCount; iRow ++) {
  427. const curRow = info.cellRange.row + iRow;
  428. const node = tree.nodes[curRow];
  429. if (!node) continue;
  430. if (!level) level = node.level;
  431. if (node.level < level) break;
  432. let bPaste = false;
  433. const data = info.sheet.zh_tree.getNodeKeyData(node);
  434. for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
  435. const curCol = info.cellRange.col + iCol;
  436. const colSetting = info.sheet.zh_setting.cols[curCol];
  437. const value = trimInvalidChar(pasteData[iRow-filterRow][iCol]);
  438. if (node.children && node.children.length > 0 && invalidFields.parent.indexOf(colSetting.field) >= 0) {
  439. toastMessageUniq(hint.parent);
  440. continue;
  441. }
  442. if (billsObj.checkNodeUsed(tree, node) && colSetting.field === 'unit_price') {
  443. toastMessageUniq (hint.usedUp);
  444. continue;
  445. }
  446. if (colSetting.type === 'Number') {
  447. const num = _.toNumber(value);
  448. if (num) {
  449. data[colSetting.field] = num;
  450. } else {
  451. try {
  452. data[colSetting.field] = math.evaluate(transExpr(value));
  453. bPaste = true;
  454. } catch (err) {
  455. toastMessageUniq(hint.invalidExpr);
  456. continue;
  457. }
  458. }
  459. } else {
  460. if (node.used && (colSetting.field ==='b_code') && data[colSetting.field] !== '' && value === '') {
  461. toastMessageUniq(hint.usedCode);
  462. continue;
  463. }
  464. data[colSetting.field] = value;
  465. }
  466. bPaste = true;
  467. }
  468. if (bPaste) {
  469. datas.push(data);
  470. } else {
  471. filterNodes.push(node);
  472. }
  473. }
  474. if (datas.length > 0) {
  475. postData('update', {postType: 'update', postData: datas}, function (result) {
  476. const refreshNode = tree.loadPostData(result);
  477. if (refreshNode.update) refreshNode.update = refreshNode.update.concat(filterNodes);
  478. billsObj.refreshTree(refreshNode);
  479. }, function () {
  480. SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
  481. });
  482. } else {
  483. SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
  484. }
  485. }
  486. }
  487. const billsObj = new BillsObj();
  488. // 清单右键菜单
  489. const billsContextMenuOptions = {
  490. selector: '#bills-spread',
  491. build: function ($trigger, e) {
  492. const target = SpreadJsObj.safeRightClickSelection($trigger, e, billsSpread);
  493. billsObj.loadRelaData();
  494. return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
  495. },
  496. items: {}
  497. };
  498. if (!readOnly) {
  499. billsContextMenuOptions.items.create = {
  500. name: '新增',
  501. icon: 'fa-sign-in',
  502. callback: function (key, opt) {
  503. billsObj.baseOpr('add');
  504. },
  505. disabled: function (key, opt) {
  506. const sheet = billsObj.sheet;
  507. const selection = sheet.getSelections();
  508. const sel = selection ? selection[0] : sheet.getSelections()[0];
  509. const row = sel ? sel.row : -1;
  510. const tree = sheet.zh_tree;
  511. if (!tree) return true;
  512. const first = sheet.zh_tree.nodes[row];
  513. const valid = !sheet.zh_setting.readOnly;
  514. return !(valid && first && first.tree_level > 1);
  515. }
  516. };
  517. billsContextMenuOptions.items.delete = {
  518. name: '删除',
  519. icon: 'fa-remove',
  520. callback: function (key, opt) {
  521. billsObj.baseOpr('delete');
  522. },
  523. disabled: function (key, opt) {
  524. const sheet = billsObj.sheet;
  525. const selection = sheet.getSelections();
  526. const sel = selection ? selection[0] : sheet.getSelections()[0];
  527. const row = sel ? sel.row : -1;
  528. const tree = sheet.zh_tree;
  529. if (!tree) return true;
  530. const first = sheet.zh_tree.nodes[row];
  531. let last = first, sameParent = true, nodeUsed = billsObj.checkNodeUsed(tree, first);
  532. if (sel.rowCount > 1 && first) {
  533. for (let r = 1; r < sel.rowCount; r++) {
  534. const rNode = tree.nodes[sel.row + r];
  535. if (!rNode) {
  536. sameParent = false;
  537. break;
  538. }
  539. nodeUsed = nodeUsed || billsObj.checkNodeUsed(tree, rNode);
  540. if (rNode.tree_level > first.tree_level) continue;
  541. if ((rNode.tree_level < first.tree_level) || (rNode.tree_level === first.tree_level && rNode.tree_pid !== first.tree_pid)) {
  542. sameParent = false;
  543. break;
  544. }
  545. last = rNode;
  546. }
  547. }
  548. const valid = !sheet.zh_setting.readOnly;
  549. return !(valid && first && sameParent && !(first.tree_level === 1) && !nodeUsed);
  550. }
  551. };
  552. }
  553. // 加载安全生产费数据
  554. postData('load', { filter: 'bills' }, function(result) {
  555. billsObj.loadData(result.bills);
  556. });
  557. const stdGclSetting = {
  558. selector: '#std-gcl',
  559. stdType: 'gcl',
  560. libs: stdBills,
  561. treeSetting: {
  562. id: 'bill_id',
  563. pid: 'pid',
  564. order: 'order',
  565. level: 'level',
  566. isLeaf: 'is_leaf',
  567. fullPath: 'full_path',
  568. rootId: -1,
  569. keys: ['id', 'list_id', 'bill_id']
  570. },
  571. spreadSetting: {
  572. cols: [
  573. {title: '清单编号', field: 'b_code', hAlign: 0, width: 170, formatter: '@', cellType: 'tree'},
  574. {title: '名称', field: 'name', hAlign: 0, width: 150, formatter: '@'},
  575. {title: '单位', field: 'unit', hAlign: 1, width: 50, formatter: '@'}
  576. ],
  577. treeCol: 0,
  578. emptyRows: 0,
  579. headRows: 1,
  580. headRowHeight: [32],
  581. defaultRowHeight: 21,
  582. headerFont: '12px 微软雅黑',
  583. font: '12px 微软雅黑',
  584. headColWidth: [30],
  585. selectedBackColor: '#fffacd',
  586. readOnly: true,
  587. },
  588. page: 'paymentSafe',
  589. tid: getTenderId(),
  590. cellDoubleClick: function (e, info) {
  591. const stdSheet = info.sheet;
  592. const stdTree = stdSheet.zh_tree;
  593. const stdNode = stdTree.nodes[info.row];
  594. if (!stdNode || !stdNode.b_code) return;
  595. const mainSheet = billsObj.sheet;
  596. if (!stdSheet.zh_setting || !stdSheet.zh_tree || !mainSheet.zh_tree) return;
  597. const mainTree = mainSheet.zh_tree;
  598. const nodes = [stdNode, ...stdTree.getAllParents(stdNode)];
  599. nodes.sort((a, b) => { return a.level - b.level; });
  600. const stdData = [];
  601. let mainChildren = mainTree.children, mainCur, checkNode;
  602. for (const sd of nodes) {
  603. const field = sd.b_code ? 'b_code' : 'name';
  604. checkNode = mainChildren.find(x => { return x[field] === sd[field]; });
  605. if (!checkNode) {
  606. stdData.push({ b_code: sd.b_code, name: sd.name, unit: sd.unit });
  607. } else {
  608. mainCur = checkNode;
  609. mainChildren = mainCur ? mainCur.children : [];
  610. }
  611. }
  612. postData('update', { postType: 'add-std',
  613. postData: {
  614. id: mainCur ? mainCur.tree_id : mainTree.setting.rootId,
  615. stdData
  616. }
  617. }, function (result) {
  618. const refreshNode = mainTree.loadPostData(result);
  619. billsObj.refreshTree(refreshNode);
  620. const node = _.find(billsObj.tree.nodes, { code: stdNode.code, name: stdNode.name });
  621. if (node) {
  622. mainSheet.setSelection(billsObj.tree.nodes.indexOf(node), sel.col, sel.rowCount, sel.colCount);
  623. SpreadJsObj.reloadRowsBackColor(mainSheet, [sel.row, billsObj.tree.nodes.indexOf(node)]);
  624. }
  625. billsObj.refreshOperationValid;
  626. billsObj.spread.focus();
  627. });
  628. },
  629. };
  630. // 展开收起标准清单
  631. $('a', '#side-menu').bind('click', function (e) {
  632. e.preventDefault();
  633. const tab = $(this), tabPanel = $(tab.attr('content'));
  634. // 展开工具栏、切换标签
  635. if (!tab.hasClass('active')) {
  636. // const close = $('.active', '#side-menu').length === 0;
  637. $('a', '#side-menu').removeClass('active');
  638. $('.tab-content .tab-select-show.tab-pane.active').removeClass('active');
  639. tab.addClass('active');
  640. tabPanel.addClass('active');
  641. // $('.tab-content .tab-pane').removeClass('active');
  642. showSideTools(tab.hasClass('active'));
  643. if (tab.attr('content') === '#std-gcl') {
  644. if (!stdGcl) stdGcl = $.stdLib(stdGclSetting);
  645. stdGcl.spread.refresh();
  646. } else if (tab.attr('content') === '#fujian') {
  647. // todo 附件
  648. }
  649. } else { // 收起工具栏
  650. tab.removeClass('active');
  651. tabPanel.removeClass('active');
  652. showSideTools(tab.hasClass('active'));
  653. }
  654. billsObj.spread.refresh();
  655. });
  656. // 工具栏spr
  657. $.divResizer({
  658. select: '#revise-right-spr',
  659. callback: function () {
  660. billsObj.spread.refresh();
  661. if (stdGcl) stdGcl.spread.refresh();
  662. }
  663. });
  664. // 导航Menu
  665. $.subMenu({
  666. menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
  667. toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
  668. key: 'menu.1.0.0',
  669. miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
  670. callback: function (info) {
  671. if (info.mini) {
  672. $('.panel-title').addClass('fluid');
  673. $('#sub-menu').removeClass('panel-sidebar');
  674. } else {
  675. $('.panel-title').removeClass('fluid');
  676. $('#sub-menu').addClass('panel-sidebar');
  677. }
  678. autoFlashHeight();
  679. billsObj.spread.refresh();
  680. if (stdGcl) stdGcl.spread.refresh();
  681. }
  682. });
  683. // 显示层次
  684. (function (select, sheet) {
  685. $(select).click(function () {
  686. if (!sheet.zh_tree) return;
  687. const tag = $(this).attr('tag');
  688. const tree = sheet.zh_tree;
  689. setTimeout(() => {
  690. showWaitingView();
  691. switch (tag) {
  692. case "1":
  693. case "2":
  694. case "3":
  695. case "4":
  696. tree.expandByLevel(parseInt(tag));
  697. SpreadJsObj.refreshTreeRowVisible(sheet);
  698. break;
  699. case "last":
  700. tree.expandByCustom(() => { return true; });
  701. SpreadJsObj.refreshTreeRowVisible(sheet);
  702. break;
  703. }
  704. closeWaitingView();
  705. }, 100);
  706. });
  707. })('a[name=showLevel]', billsObj.sheet);
  708. });