revise_price.js 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date
  7. * @version
  8. */
  9. const showSideTools = function (show) {
  10. const left = $('#left-view'), right = $('#right-view'), parent = left.parent();
  11. if (show) {
  12. right.show();
  13. autoFlashHeight();
  14. const percent = 100 - right.outerWidth() /parent.width() * 100;
  15. left.css('width', percent + '%');
  16. } else {
  17. left.width(parent.width());
  18. right.hide();
  19. }
  20. };
  21. const setPriceHint = function (show) {
  22. const hinticon = show ? 'fa-bell' : undefined;
  23. subMiniMenu.$children[2].hinticon = hinticon;
  24. subMenu.$children[2].hinticon = hinticon;
  25. };
  26. $(document).ready(() => {
  27. const ledgerGclSpreadSetting = {
  28. cols: [
  29. { title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 80, formatter: '@' },
  30. { title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 200, formatter: '@' },
  31. { title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@' },
  32. { title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 80, type: 'Number' },
  33. ],
  34. emptyRows: 0,
  35. headRows: 1,
  36. headRowHeight: [32],
  37. headColWidth: [30],
  38. defaultRowHeight: 21,
  39. headerFont: '12px 微软雅黑',
  40. font: '12px 微软雅黑',
  41. readOnly: true,
  42. };
  43. const ledgerXmjSpreadSetting = {
  44. cols: [
  45. {title: '项目节编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 100, formatter: '@'},
  46. {title: '单位工程', colSpan: '1', rowSpan: '1', field: 'dwgc', hAlign: 0, width: 80, formatter: '@'},
  47. {title: '分部工程', colSpan: '1', rowSpan: '1', field: 'fbgc', hAlign: 0, width: 80, formatter: '@'},
  48. {title: '分项工程', colSpan: '1', rowSpan: '1', field: 'fxgc', hAlign: 0, width: 80, formatter: '@'},
  49. {title: '细目', colSpan: '1', rowSpan: '1', field: 'jldy', hAlign: 0, width: 80, formatter: '@'},
  50. {title: '计量单元', colSpan: '1', rowSpan: '1', field: 'bwmx', hAlign: 0, width: 80, formatter: '@'},
  51. ],
  52. emptyRows: 0,
  53. headRows: 1,
  54. headRowHeight: [32],
  55. headColWidth: [30],
  56. defaultRowHeight: 21,
  57. headerFont: '12px 微软雅黑',
  58. font: '12px 微软雅黑',
  59. readOnly: true,
  60. };
  61. const priceSpreadSetting = {
  62. cols: [
  63. { title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 100, formatter: '@', readOnly: true },
  64. { title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 210, formatter: '@', readOnly: true },
  65. { title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true },
  66. { title: '当前单价', colSpan: '1', rowSpan: '2', field: 'org_price', hAlign: 2, width: 80, type: 'Number', readOnly: true },
  67. { title: '调整后单价', colSpan: '1', rowSpan: '2', field: 'new_price', hAlign: 2, width: 80, type: 'Number' },
  68. { title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 2, width: 150, formatter: '@' },
  69. ],
  70. emptyRows: 0,
  71. headRows: 1,
  72. headRowHeight: [32],
  73. headColWidth: [30],
  74. defaultRowHeight: 21,
  75. headerFont: '12px 微软雅黑',
  76. font: '12px 微软雅黑',
  77. readOnly,
  78. getColor: function (sheet, data, row, col, defaultColor) {
  79. if (!data || data.rela_lid) return defaultColor;
  80. const samePrice = sheet.zh_data.find(x => {
  81. return x.b_code === data.b_code && x.name === data.name && x.unit === data.unit && x.org_price === data.org_price;
  82. });
  83. return samePrice ? '#f5deb3' : defaultColor;
  84. }
  85. };
  86. const priceBwSpreadSetting = {
  87. cols: [
  88. {title: '项目节编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 150, formatter: '@', cellType: 'tree'},
  89. {title: '清单编号', colSpan: '1', rowSpan: '1', field: 'b_code', hAlign: 0, width: 80, formatter: '@'},
  90. {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 230, formatter: '@'},
  91. {title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 60, formatter: '@'},
  92. ],
  93. headRows: 1,
  94. emptyRows: 0,
  95. headRowHeight: [25],
  96. defaultRowHeight: 21,
  97. headerFont: '12px 微软雅黑',
  98. font: '12px 微软雅黑',
  99. readOnly: true,
  100. getColor: function (sheet, data, row, col, defaultColor) {
  101. return data && data.valid ? defaultColor : '#ddd';
  102. },
  103. };
  104. sjsSettingObj.setFxTreeStyle(priceBwSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
  105. const priceChangeSpreadSetting = {
  106. cols: [
  107. {title: '变更令', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 80, formatter: '@'},
  108. {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 230, formatter: '@'},
  109. {title: '批复文号', colSpan: '1', rowSpan: '1', field: 'w_code', hAlign: 1, width: 80, formatter: '@'},
  110. ],
  111. headRows: 1,
  112. emptyRows: 0,
  113. headRowHeight: [25],
  114. defaultRowHeight: 21,
  115. headerFont: '12px 微软雅黑',
  116. font: '12px 微软雅黑',
  117. readOnly: true,
  118. getColor: function (sheet, data, row, col, defaultColor) {
  119. return data && data.rela ? defaultColor : '#ddd';
  120. },
  121. };
  122. autoFlashHeight();
  123. const bcontent = $(".bcontent-wrap").length > 0 ? $(".bcontent-wrap").height() : 0;
  124. $(".sp-wrap").height(bcontent-30);
  125. const priceSpread = SpreadJsObj.createNewSpread($('#price-spread')[0]);
  126. const priceSheet = priceSpread.getActiveSheet();
  127. const priceBwSpread = SpreadJsObj.createNewSpread($('#price-bw-spread')[0]);
  128. const priceBwSheet = priceBwSpread.getActiveSheet();
  129. const priceChangeSpread = SpreadJsObj.createNewSpread($('#price-change-spread')[0]);
  130. const priceChangeSheet = priceChangeSpread.getActiveSheet();
  131. SpreadJsObj.initSheet(priceSheet, priceSpreadSetting);
  132. SpreadJsObj.initSheet(priceBwSheet, priceBwSpreadSetting);
  133. SpreadJsObj.initSheet(priceChangeSheet, priceChangeSpreadSetting);
  134. class RevisePrice {
  135. constructor () {
  136. this.data = [];
  137. this.tree = createNewPathTree('filter', {
  138. id: 'ledger_id',
  139. pid: 'ledger_pid',
  140. order: 'order',
  141. level: 'level',
  142. rootId: -1,
  143. fullPath: 'full_path',
  144. keys: ['id', 'tender_id', 'ledger_id'],
  145. });
  146. }
  147. resortData() {
  148. this.data.sort(function (a, b) {
  149. return a.order - b.order;
  150. });
  151. }
  152. analysisRelaLid(price) {
  153. const tree = this.tree;
  154. const rela_lid = price.rela_lid ? price.rela_lid.split(',') : [];
  155. price.rela_hint = rela_lid.map(x => {
  156. const node = tree.getItems(parseInt(x));
  157. return node ? node.code || node.name : '';
  158. }).join(',');
  159. }
  160. loadDatas(datas, treeData, changeData) {
  161. this.data = datas;
  162. this.tree.loadDatas(treeData);
  163. this.resortData();
  164. for (const d of this.data) {
  165. this.analysisRelaLid(d);
  166. }
  167. this.change = changeData;
  168. if (this.data.length > 0) this.refreshRela(this.data[0]);
  169. }
  170. loadUpdateData(updateData) {
  171. if (updateData.add) {
  172. for (const a of updateData.add) {
  173. this.data.push(a);
  174. this.analysisRelaLid(a);
  175. }
  176. }
  177. if (updateData.update) {
  178. for (const u of updateData.update) {
  179. const d = this.data.find(function (x) {
  180. return u.id === x.id;
  181. });
  182. if (d) {
  183. _.assign(d, u);
  184. } else {
  185. this.data.push(d);
  186. }
  187. this.analysisRelaLid(d);
  188. }
  189. }
  190. if (updateData.del) {
  191. _.remove(this.data, function (d) {
  192. return updateData.del.indexOf(d.id) >= 0;
  193. });
  194. }
  195. this.resortData();
  196. }
  197. getSamePrice(price) {
  198. return this.data.filter(x => {
  199. if (x.id === price.id) return false;
  200. return x.b_code === price.b_code && x.name === price.name && x.unit === price.unit && x.org_price === price.org_price;
  201. });
  202. }
  203. refreshTreeRela(price, samePrice) {
  204. if (price.rela_lid) {
  205. const choose = price.rela_lid.split(',');
  206. for (const node of this.tree.nodes) {
  207. node.rela = choose.indexOf(node.ledger_id + '') >= 0;
  208. }
  209. for (const node of this.tree.nodes) {
  210. node.valid = node.rela || this.tree.checkParent(node, 'rela') || this.tree.checkChildren(node, 'rela');
  211. }
  212. } else {
  213. const invalid = [];
  214. for (const sp of samePrice) {
  215. const lid = sp.rela_lid ? sp.rela_lid.split(',') : [];
  216. invalid.push(...lid);
  217. }
  218. for (const node of this.tree.nodes) {
  219. node.rela = invalid.indexOf(node.ledger_id + '') >= 0;
  220. }
  221. for (const node of this.tree.nodes) {
  222. node.valid = !(node.rela || this.tree.checkParent(node, 'rela'));
  223. }
  224. }
  225. }
  226. refreshChangeRela(price, samePrice) {
  227. if (price.rela_cid) {
  228. const choose = price.rela_cid.split(',');
  229. for (const c of this.change) {
  230. c.rela = choose.indexOf(c.cid + '') >= 0;
  231. }
  232. } else {
  233. const invalid = [];
  234. for (const sp of samePrice) {
  235. const cid = sp.rela_cid ? sp.rela_cid.split(',') : [];
  236. invalid.push(...cid);
  237. }
  238. for (const c of this.change) {
  239. c.rela = invalid.indexOf(c.cid + '') < 0;
  240. }
  241. }
  242. }
  243. refreshRela(price) {
  244. const samePrice = this.getSamePrice(price);
  245. this.refreshTreeRela(price, samePrice);
  246. this.refreshChangeRela(price, samePrice);
  247. }
  248. }
  249. const revisePrice = new RevisePrice();
  250. const priceOprObj = {
  251. addRevisePrice(data) {
  252. const op = revisePrice.data.find(x => {
  253. return x.b_code === data.b_code && x.name === x.name && x.unit === x.unit && checkZero(ZhCalc.sub(x.org_price, data.unit_price)) && (!x.rela_lid || !x.rela_cid);
  254. });
  255. if (op) {
  256. toastr.warning('已存在该单价调整');
  257. SpreadJsObj.locateData(priceSheet, op);
  258. return;
  259. }
  260. postData(window.location.pathname + '/update', { add: { b_code: data.b_code, name: data.name, unit: data.unit, unit_price: data.unit_price } }, result => {
  261. revisePrice.loadUpdateData(result);
  262. SpreadJsObj.reLoadSheetData(priceSheet);
  263. setPriceHint(revisePrice.data.length > 0);
  264. });
  265. },
  266. /**
  267. * 删除按钮响应事件
  268. * @param sheet
  269. */
  270. deletePress: function (sheet) {
  271. if (!sheet.zh_setting || readOnly) return;
  272. const sortData = sheet.zh_data;
  273. const datas = [];
  274. const sels = sheet.getSelections();
  275. if (!sels || !sels[0]) return;
  276. for (let iRow = sels[0].row; iRow < sels[0].row + sels[0].rowCount; iRow++) {
  277. let bDel = false;
  278. const node = sortData[iRow];
  279. if (node) {
  280. const data = {id: node.id};
  281. for (let iCol = sels[0].col; iCol < sels[0].col + sels[0].colCount; iCol++) {
  282. const style = sheet.getStyle(iRow, iCol);
  283. if (!style.locked) {
  284. const colSetting = sheet.zh_setting.cols[iCol];
  285. data[colSetting.field] = null;
  286. bDel = true;
  287. }
  288. }
  289. if (bDel) {
  290. datas.push(data);
  291. }
  292. }
  293. }
  294. if (datas.length > 0) {
  295. postData(window.location.pathname + '/update', {update: datas}, function (result) {
  296. revisePrice.loadUpdateData(result);
  297. SpreadJsObj.reLoadSheetData(priceSheet);
  298. }, function () {
  299. SpreadJsObj.reLoadSheetData(priceSheet);
  300. });
  301. }
  302. },
  303. delete: function (sheet) {
  304. if (!sheet.zh_setting || readOnly) return;
  305. const sortData = sheet.zh_data;
  306. const datas = [];
  307. const sels = sheet.getSelections();
  308. if (!sels || !sels[0]) return;
  309. for (let iRow = sels[0].row, iLen = sels[0].row + sels[0].rowCount; iRow < iLen; iRow++) {
  310. const node = sortData[iRow];
  311. datas.push(node.id);
  312. }
  313. if (datas.length > 0) {
  314. postData(window.location.pathname + '/update', {del: datas}, function (result) {
  315. revisePrice.loadUpdateData(result);
  316. SpreadJsObj.reLoadSheetData(priceSheet);
  317. setPriceHint(revisePrice.data.length > 0);
  318. }, function () {
  319. SpreadJsObj.reLoadSheetData(priceSheet);
  320. });
  321. }
  322. },
  323. editEnded: function (e, info) {
  324. if (!info.sheet.zh_setting || !info.sheet.zh_data) return;
  325. const node = info.sheet.zh_data[info.row];
  326. if (!node) return;
  327. const col = info.sheet.zh_setting.cols[info.col];
  328. const data = { update: { id: node.id, org_price: node.org_price } };
  329. const oldValue = node ? node[col.field] : null;
  330. const newValue = trimInvalidChar(info.editingText);
  331. if (oldValue == info.editingText || ((!oldValue || oldValue === '') && (newValue === ''))) {
  332. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  333. return;
  334. }
  335. if (col.type === 'Number') {
  336. const num = _.toNumber(newValue);
  337. if (num) data.update[col.field] = num;
  338. } else {
  339. data.update[col.field] = newValue;
  340. }
  341. postData(window.location.pathname + '/update', data, function (result) {
  342. revisePrice.loadUpdateData(result);
  343. SpreadJsObj.reLoadSheetData(info.sheet);
  344. }, function () {
  345. SpreadJsObj.reLoadRowData(info.sheet, info.row);
  346. });
  347. },
  348. clipboardPasting(e, info) {
  349. const setting = info.sheet.zh_setting, sortData = info.sheet.zh_data;
  350. info.cancel = true;
  351. if (!setting || !sortData) return;
  352. const pasteData = info.pasteData.html
  353. ? SpreadJsObj.analysisPasteHtml(info.pasteData.html)
  354. : (info.pasteData.text === ''
  355. ? SpreadJsObj.Clipboard.getAnalysisPasteText()
  356. : SpreadJsObj.analysisPasteText(info.pasteData.text));
  357. const uDatas = [];
  358. for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
  359. const curRow = info.cellRange.row + iRow;
  360. const node = sortData[curRow];
  361. let bPaste = false;
  362. const data = {};
  363. for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
  364. const curCol = info.cellRange.col + iCol;
  365. const colSetting = setting.cols[curCol];
  366. const value = trimInvalidChar(pasteData[iRow][iCol]);
  367. if (colSetting.type === 'Number') {
  368. const num = _.toNumber(value);
  369. if (num) {
  370. data[colSetting.field] = num;
  371. bPaste = true;
  372. }
  373. } else {
  374. data[colSetting.field] = value;
  375. bPaste = true;
  376. }
  377. }
  378. if (bPaste) {
  379. data.id = node.id;
  380. uDatas.push(data);
  381. }
  382. }
  383. const updateData = {};
  384. if (uDatas.length > 0) updateData.update = uDatas;
  385. if (uDatas.length > 0) {
  386. postData(window.location.pathname + '/update', updateData, function (result) {
  387. revisePrice.loadUpdateData(result);
  388. SpreadJsObj.reLoadSheetData(info.sheet);
  389. });
  390. } else {
  391. SpreadJsObj.reLoadSheetData(info.sheet);
  392. }
  393. },
  394. upMove: function () {
  395. const sels = priceSheet.getSelections(), sortData = priceSheet.zh_data;
  396. const node = sortData[sels[0].row];
  397. const preNode = sortData[sels[0].row - 1];
  398. const data = [
  399. {id: node.id, order: preNode.order},
  400. {id: preNode.id, order: node.order}
  401. ];
  402. postData(window.location.pathname + '/update', {update: data}, function (result) {
  403. revisePrice.loadUpdateData(result);
  404. SpreadJsObj.reLoadRowsData(priceSheet, [sels[0].row, sels[0].row - 1]);
  405. priceSheet.setSelection(sels[0].row - 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
  406. });
  407. },
  408. downMove: function () {
  409. const sels = priceSheet.getSelections(), sortData = priceSheet.zh_data;
  410. const node = sortData[sels[0].row];
  411. const nextNode = sortData[sels[0].row + 1];
  412. const data = [
  413. {id: node.id, order: nextNode.order},
  414. {id: nextNode.id, order: node.order}
  415. ];
  416. postData(window.location.pathname + '/update', {update: data}, function (result) {
  417. revisePrice.loadUpdateData(result);
  418. SpreadJsObj.reLoadRowsData(priceSheet, [sels[0].row, sels[0].row + 1]);
  419. priceSheet.setSelection(sels[0].row + 1, sels[0].col, sels[0].rowCount, sels[0].colCount);
  420. });
  421. },
  422. updateRelaLid: function (price, rela_lid) {
  423. const data = { update: { id: price.id, rela_lid } };
  424. postData(window.location.pathname + '/update', data, function (result) {
  425. revisePrice.loadUpdateData(result);
  426. SpreadJsObj.reLoadSheetData(priceSheet);
  427. });
  428. },
  429. selectionChanged: function () {
  430. const price = SpreadJsObj.getSelectObject(priceSheet);
  431. revisePrice.refreshRela(price);
  432. SpreadJsObj.reloadRowBackColor(priceBwSheet, 0, priceBwSheet.getRowCount());
  433. SpreadJsObj.reloadRowBackColor(priceChangeSheet, 0, priceChangeSheet.getRowCount());
  434. },
  435. };
  436. if (!readOnly) {
  437. priceSheet.bind(spreadNS.Events.EditEnded, priceOprObj.editEnded);
  438. priceSheet.bind(spreadNS.Events.ClipboardPasting, priceOprObj.clipboardPasting);
  439. SpreadJsObj.addDeleteBind(priceSpread, priceOprObj.deletePress);
  440. $.contextMenu({
  441. selector: '#price-spread',
  442. build: function ($trigger, e) {
  443. const target = SpreadJsObj.safeRightClickSelection($trigger, e, priceSpread);
  444. return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
  445. },
  446. items: {
  447. del: {
  448. name: '删除',
  449. icon: 'fa-remove',
  450. callback: function (key, opt) {
  451. priceOprObj.delete(priceSheet);
  452. },
  453. disabled: function (key, opt) {
  454. const node = SpreadJsObj.getSelectObject(priceSheet);
  455. return node === undefined || node === null;
  456. },
  457. visible: function (key, opt) {
  458. return !readOnly;
  459. }
  460. },
  461. sprDel: '----',
  462. upMove: {
  463. name: '上移',
  464. icon: 'fa-arrow-up',
  465. callback: function (key, opt) {
  466. priceOprObj.upMove();
  467. },
  468. disabled: function (key, opt) {
  469. const sels = priceSheet.getSelections();
  470. if (!sels || !sels[0] || sels[0].row === 0) return true;
  471. const row = sels[0].row;
  472. const node = revisePrice.data[row];
  473. return node === undefined || node === null;
  474. },
  475. visible: function (key, opt) {
  476. return !readOnly;
  477. }
  478. },
  479. downMove: {
  480. name: '下移',
  481. icon: 'fa-arrow-down',
  482. callback: function (key, opt) {
  483. priceOprObj.downMove();
  484. },
  485. disabled: function (key, opt) {
  486. const sels = priceSheet.getSelections();
  487. if (!sels || !sels[0] || sels[0].row >= revisePrice.data.length - 1) return true;
  488. const row = sels[0].row;
  489. const node = revisePrice.data[row];
  490. return node === undefined || node === null;
  491. },
  492. visible: function (key, opt) {
  493. return !readOnly;
  494. }
  495. },
  496. sprMove: '----',
  497. chooseRelaBw: {
  498. name: '选择应用部位',
  499. icon: 'fa-tags',
  500. callback: function (key, opt) {
  501. const price = SpreadJsObj.getSelectObject(priceSheet);
  502. const samePrice = revisePrice.getSamePrice(price);
  503. chooseRelaBw.show(price, samePrice);
  504. },
  505. disabled: function (key, opt) {
  506. const node = SpreadJsObj.getSelectObject(priceSheet);
  507. return !node;
  508. },
  509. visible: function (key, opt) {
  510. return !readOnly;
  511. }
  512. },
  513. chooseRelaChange: {
  514. name: '选择应用变更令',
  515. icon: 'fa-tags',
  516. callback: function (key, opt) {
  517. const price = SpreadJsObj.getSelectObject(priceSheet);
  518. const samePrice = revisePrice.getSamePrice(price);
  519. // todo
  520. // chooseRelaChange.show(price, samePrice);
  521. },
  522. disabled: function (key, opt) {
  523. const node = SpreadJsObj.getSelectObject(priceSheet);
  524. return !node;
  525. },
  526. visible: function (key, opt) {
  527. return !readOnly;
  528. }
  529. },
  530. },
  531. });
  532. }
  533. priceSpread.bind(spreadNS.Events.SelectionChanged, priceOprObj.selectionChanged);
  534. class LedgerGcl {
  535. constructor(setting) {
  536. this.setting = setting;
  537. this.spread = SpreadJsObj.createNewSpread($(this.setting.selector)[0]);
  538. this.sheet = this.spread.getActiveSheet();
  539. SpreadJsObj.initSheet(this.sheet, this.setting.spreadSetting);
  540. this.xmjSpread = SpreadJsObj.createNewSpread($(this.setting.xmjSelector)[0]);
  541. this.xmjSheet = this.xmjSpread.getActiveSheet();
  542. SpreadJsObj.initSheet(this.xmjSheet, this.setting.xmjSpreadSetting);
  543. if (!readOnly) {
  544. this.spread.bind(spreadNS.Events.CellDoubleClick, function (e, info) {
  545. const gcl = SpreadJsObj.getSelectObject(info.sheet);
  546. priceOprObj.addRevisePrice(gcl);
  547. });
  548. }
  549. const self = this;
  550. this.spread.bind(spreadNS.Events.SelectionChanged, function (e, info) {
  551. self.loadLeafXmj();
  552. });
  553. }
  554. loadData(bills, pos) {
  555. gclGatherModel.loadLedgerData(bills);
  556. gclGatherModel.loadPosData(pos);
  557. this.gcl = gclGatherModel.gatherGclData();
  558. this.sheet && SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Data, this.gcl);
  559. this.loadLeafXmj(0);
  560. }
  561. loadLeafXmj(iGclRow) {
  562. const gcl = iGclRow ? this.gcl[iGclRow] : SpreadJsObj.getSelectObject(this.sheet);
  563. SpreadJsObj.resetTopAndSelect(this.xmjSheet);
  564. if (gcl) {
  565. SpreadJsObj.loadSheetData(this.xmjSheet, SpreadJsObj.DataType.Data, gcl.leafXmjs);
  566. } else {
  567. SpreadJsObj.loadSheetData(this.xmjSheet, SpreadJsObj.DataType.Data, []);
  568. }
  569. }
  570. }
  571. const ledgerGcl = new LedgerGcl({
  572. selector: '#ledger-gcl-spread',
  573. spreadSetting: ledgerGclSpreadSetting,
  574. xmjSelector: '#ledger-xmj-spread',
  575. xmjSpreadSetting: ledgerXmjSpreadSetting,
  576. });
  577. $.subMenu({
  578. menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
  579. toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
  580. key: 'menu.1.0.0',
  581. miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
  582. callback: function (info) {
  583. if (info.mini) {
  584. $('.panel-title').addClass('fluid');
  585. $('#sub-menu').removeClass('panel-sidebar');
  586. } else {
  587. $('.panel-title').removeClass('fluid');
  588. $('#sub-menu').addClass('panel-sidebar');
  589. }
  590. autoFlashHeight();
  591. priceSpread.refresh();
  592. ledgerGcl.spread.refresh();
  593. }
  594. });
  595. $.divResizer({
  596. select: '#revise-right-spr',
  597. callback: function () {
  598. priceSpread.refresh();
  599. priceBwSpread.refresh();
  600. priceChangeSpread.refresh();
  601. ledgerGcl.spread.refresh();
  602. ledgerGcl.xmjSpread.refresh();
  603. }
  604. });
  605. $.divResizer({
  606. select: '#gcl-spr',
  607. callback: function () {
  608. ledgerGcl.spread.refresh();
  609. ledgerGcl.xmjSpread.refresh();
  610. }
  611. });
  612. $.divResizer({
  613. select: '#price-resize',
  614. callback: function () {
  615. priceSpread.refresh();
  616. let bcontent = $(".bcontent-wrap").length > 0 ? $(".bcontent-wrap").height() : 0;
  617. $(".sp-wrap").height(bcontent-30);
  618. priceBwSpread.refresh();
  619. priceChangeSpread.refresh();
  620. }
  621. });
  622. class ChooseRelaBw {
  623. constructor() {
  624. const self = this;
  625. this.tree = createNewPathTree('base', {
  626. id: 'ledger_id',
  627. pid: 'ledger_pid',
  628. order: 'order',
  629. level: 'level',
  630. rootId: -1,
  631. fullPath: 'full_path',
  632. keys: ['id', 'tender_id', 'ledger_id'],
  633. });
  634. $('#choose-rela-bw').on('shown.bs.modal', function() {
  635. self.initSpread();
  636. SpreadJsObj.reloadColData(self.sheet, 0, 1);
  637. SpreadJsObj.reloadRowBackColor(self.sheet, 0, self.tree.nodes.length);
  638. });
  639. $('#choose-rela-bw-ok').click(function() {
  640. const choose_lid = [];
  641. self.tree.nodes.forEach(x => {
  642. if (x.check) choose_lid.push(x.ledger_id);
  643. });
  644. priceOprObj.updateRelaLid(self.price, choose_lid.join(','));
  645. $('#choose-rela-bw').modal('hide');
  646. });
  647. }
  648. initSpread() {
  649. if (this.spread) return;
  650. this.spread = SpreadJsObj.createNewSpread($('#rela-bw-spread')[0]);
  651. this.sheet = this.spread.getActiveSheet();
  652. const spreadSetting = {
  653. cols: [
  654. {title: '选择', colSpan: '1', rowSpan: '1', field: 'check', hAlign: 1, width: 50, formatter: '@', readOnly: true, cellType: 'checkbox'},
  655. {title: '项目节编号', colSpan: '1', rowSpan: '1', field: 'code', hAlign: 0, width: 150, formatter: '@', readOnly: true, cellType: 'tree'},
  656. {title: '清单编号', colSpan: '1', rowSpan: '1', field: 'b_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
  657. {title: '名称', colSpan: '1', rowSpan: '1', field: 'name', hAlign: 0, width: 230, formatter: '@', readOnly: true},
  658. {title: '单位', colSpan: '1', rowSpan: '1', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true},
  659. ],
  660. headRows: 1,
  661. emptyRows: 0,
  662. headRowHeight: [25],
  663. defaultRowHeight: 21,
  664. headerFont: '12px 微软雅黑',
  665. font: '12px 微软雅黑',
  666. getColor: function (sheet, data, row, col, defaultColor) {
  667. return data && data.invalid ? '#dddddd' : defaultColor;
  668. }
  669. };
  670. sjsSettingObj.setFxTreeStyle(spreadSetting, sjsSettingObj.FxTreeStyle.jz);
  671. SpreadJsObj.initSheet(this.sheet, spreadSetting);
  672. const self = this;
  673. this.spread.bind(spreadNS.Events.ButtonClicked, function (e, info) {
  674. function checkInvalid(node) {
  675. if (node.invalid) return 1;
  676. if (self.tree.checkParent(node, 'invalid')) return 2;
  677. if (self.tree.checkChildren(node, 'invalid')) return 3;
  678. return 0;
  679. }
  680. const sheet = info.sheet, cellType = sheet.getCellType(info.row, info.col);
  681. if (!sheet.zh_setting) return;
  682. if (cellType instanceof spreadNS.CellTypes.CheckBox) {
  683. if (sheet.isEditing()) sheet.endEdit(true);
  684. }
  685. const col = sheet.zh_setting.cols[info.col];
  686. if (col.field !== 'check') return;
  687. const tree = sheet.zh_tree;
  688. const node = SpreadJsObj.getSelectObject(sheet);
  689. if (node.b_code) {
  690. toastr.warning('请选择部位');
  691. return;
  692. }
  693. if (!node.check) {
  694. const invalid = checkInvalid(node);
  695. const invalidHint = ['该部位已被选择,请勿重复选择', '该部位的父项已被选择,请勿选择', '该部位的子项已被选择,请勿在其子项中选择'];
  696. if (invalid) {
  697. toastr.warning(invalidHint[invalid-1]);
  698. return;
  699. }
  700. if (self.tree.checkParent(node)) {
  701. const rect = info.sheet.getCellRect(info.row, info.col);
  702. self.chooseConfirmPopover({
  703. x: rect.x + rect.width / 2 + 25,
  704. y: rect.y + rect.height / 2 + 3,
  705. }, '父项已勾选,继续将取消父项勾选。', function () {
  706. node.check = true;
  707. const parents = tree.getFullPathNodes(tree.getParent(node).full_path);
  708. const rows = [tree.nodes.indexOf(node)];
  709. for (const p of parents) {
  710. if (p.check) {
  711. p.check = false;
  712. rows.push(tree.nodes.indexOf(p));
  713. }
  714. }
  715. SpreadJsObj.reLoadRowsData(info.sheet, rows);
  716. });
  717. } else if (self.tree.checkChildren(node)) {
  718. const rect = info.sheet.getCellRect(info.row, info.col);
  719. self.chooseConfirmPopover({
  720. x: rect.x + rect.width / 2 + 25,
  721. y: rect.y + rect.height / 2 + 3,
  722. }, '子项已勾选,继续将取消子项勾选。', function () {
  723. node.check = true;
  724. const posterity = tree.getPosterity(node);
  725. const rows = [tree.nodes.indexOf(node)];
  726. for (const p of posterity) {
  727. if (p.check) {
  728. rows.push(tree.nodes.indexOf(p));
  729. p.check = false;
  730. }
  731. }
  732. SpreadJsObj.reLoadRowsData(info.sheet, rows);
  733. });
  734. } else {
  735. node.check = true;
  736. SpreadJsObj.reLoadRowsData(info.sheet, [info.row]);
  737. }
  738. } else {
  739. node.check = false;
  740. SpreadJsObj.reLoadRowsData(info.sheet, [info.row]);
  741. }
  742. });
  743. SpreadJsObj.loadSheetData(this.sheet, SpreadJsObj.DataType.Tree, this.tree);
  744. }
  745. reBind(obj, eventName, fun) {
  746. obj.unbind(eventName);
  747. obj.bind(eventName, fun);
  748. }
  749. chooseConfirmPopover(pos, hint, okCallback) {
  750. const confirmObj = $('#choose-confirm'), hintObj = $('#choose-confirm-hint');
  751. const okObj = $('#choose-confirm-ok'), cancelObj = $('#choose-confirm-cancel');
  752. this.reBind(cancelObj, 'click', function () {
  753. confirmObj.hide();
  754. });
  755. this.reBind(okObj, 'click', function () {
  756. okCallback();
  757. confirmObj.hide();
  758. });
  759. hintObj.text(hint);
  760. confirmObj.css("top", pos.y).css("left", pos.x).show();
  761. }
  762. loadTree(data) {
  763. this.tree.loadDatas(data);
  764. }
  765. show(price, samePrice){
  766. this.price = price;
  767. this.choose = price.rela_lid ? price.rela_lid.split(',') : [];
  768. this.invalid = [];
  769. for (const sp of samePrice) {
  770. const lid = sp.rela_lid ? sp.rela_lid.split(',') : [];
  771. this.invalid.push(...lid);
  772. }
  773. for (const node of this.tree.nodes) {
  774. node.check = this.choose.indexOf(node.ledger_id + '') >= 0;
  775. node.invalid = this.invalid.indexOf(node.ledger_id + '') >= 0;
  776. }
  777. $('#choose-rela-bw').modal('show');
  778. }
  779. }
  780. const chooseRelaBw = new ChooseRelaBw();
  781. postData('load', { filter: 'bills;pos;price;change' }, result => {
  782. revisePrice.loadDatas(result.price, result.bills, result.change);
  783. SpreadJsObj.loadSheetData(priceSheet, SpreadJsObj.DataType.Data, revisePrice.data);
  784. ledgerGcl.loadData(result.bills, result.pos);
  785. chooseRelaBw.loadTree(result.bills);
  786. SpreadJsObj.loadSheetData(priceBwSheet, SpreadJsObj.DataType.Tree, revisePrice.tree);
  787. SpreadJsObj.loadSheetData(priceChangeSheet, SpreadJsObj.DataType.Data, revisePrice.change);
  788. $("[content='#ledgerGcl']").click();
  789. });
  790. $('a', '#side-menu').bind('click', function (e) {
  791. e.preventDefault();
  792. const tab = $(this), tabPanel = $(tab.attr('content'));
  793. // 展开工具栏、切换标签
  794. if (!tab.hasClass('active')) {
  795. $('a', '#side-menu').removeClass('active');
  796. tab.addClass('active');
  797. $('.tab-content .tab-pane').removeClass('active');
  798. tabPanel.addClass('active');
  799. showSideTools(tab.hasClass('active'));
  800. ledgerGcl.spread.refresh();
  801. ledgerGcl.xmjSpread.refresh();
  802. } else {// 收起工具栏
  803. tab.removeClass('active');
  804. tabPanel.removeClass('active');
  805. showSideTools(tab.hasClass('active'));
  806. }
  807. priceSpread.refresh();
  808. });
  809. });