revise_price.js 40 KB

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