revise_price.js 43 KB

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