revise_price.js 44 KB

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