revise_price.js 44 KB

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