revise_price.js 48 KB

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