revise_price.js 41 KB

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