revise_price.js 45 KB

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