mbzm_view.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /**
  2. * Created by zhang on 2018/11/26.
  3. */
  4. let mbzm_obj={
  5. spread:null,
  6. nodeChanged:false,
  7. datas:[],
  8. locateMap:{
  9. INMEASURE:1,
  10. INFBFX:2,
  11. AFTERRATION:3
  12. },
  13. setting:{
  14. header: [
  15. {headerName: "编码", headerWidth: 130, dataCode: "code", dataType: "String", formatter: "@"},
  16. {headerName: "模板类别", headerWidth: 260, dataCode: "name", dataType: "String", hAlign: "left"},
  17. {headerName: "系数", headerWidth: 65, dataCode: "coe", dataType: "Number",validator:"number"},
  18. {headerName: "单位", headerWidth: 45, dataCode: "unit", dataType: "String", hAlign: "center",getText:'forUnit'},
  19. {headerName: "工程量", headerWidth: 65, dataCode: "quantity", dataType: "Number",validator:"number"},
  20. {headerName: "关联类别", headerWidth: 100, dataCode: "type", dataType: "String"},
  21. {headerName: "清单位置", headerWidth: 200, dataCode: "position", hAlign: "left", dataType: "String",cellType:'selectButton',getText:'forPosition'},
  22. ],
  23. view: {
  24. lockColumns:["code","name","unit","type"],
  25. rowHeaderWidth:25
  26. },
  27. getText:{
  28. forPosition:function (item) {
  29. let createL = $('#createLocation').val();
  30. if(createL == mbzm_obj.locateMap.INMEASURE) return mbzm_obj.getDisplayText(item.billID,item.billsLocation);
  31. if(createL == mbzm_obj.locateMap.INFBFX) return mbzm_obj.getDisplayText(item.fxID,"");
  32. return ""
  33. },
  34. forUnit:function (item) {//这里显示的单位是去掉定额单位前面的数字的结果
  35. return item.unit &&_.isString(item.unit)?item.unit.replace(/^\d+/,""):""
  36. }
  37. }
  38. },
  39. getDisplayText:function (billID,position) {
  40. if(billID && billID!=''){
  41. let node = projectObj.project.mainTree.getNodeByID(billID);
  42. if(node){
  43. let code = node.data.code?node.data.code:"";
  44. let name = node.data.name?node.data.name:"";
  45. return code +" "+name;
  46. }
  47. }
  48. return position;
  49. },
  50. //当点击应用的时候才保存数据
  51. initSpread:function () {
  52. this.spread = SheetDataHelper.createNewSpread($("#mbzmSpread")[0]);
  53. sheetCommonObj.spreadDefaultStyle(this.spread);
  54. this.sheet = this.spread.getSheet(0);
  55. sheetCommonObj.initSheet(this.sheet, this.setting);
  56. this.sheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onSheetValueChange);
  57. this.spread.bind(GC.Spread.Sheets.Events.ButtonClicked, installationFeeObj.onPositionButtonClick);//共用一个位置选择器
  58. this.sheet.name('ration_template');
  59. },
  60. refresh:function () {
  61. let total = $('#mbzmSpread').parent().height();
  62. let b_height = $('#mbzmSpread').prev('.col-12').height();
  63. $('#mbzmSpread').css('height',total- b_height);
  64. this.spread?this.spread.refresh():this.initSpread();
  65. },
  66. refreshSheetData:function () {
  67. sheetCommonObj.showData(this.sheet, this.setting,this.datas);
  68. },
  69. showMBZMData:function(node){
  70. let selected = node?node:projectObj.project.mainTree.selected;
  71. if(this.nodeChanged == true){//选中的行改变了才做初始化,刷新当前缓存, 在project_view 中treeSelectedChanged方法里设置
  72. let datas = [];
  73. $("#createLocation").val(this.locateMap.INMEASURE);//初始化
  74. if(selected&&selected.sourceType == ModuleNames.ration){
  75. let ration = selected.data;
  76. let template = projectObj.project.ration_template.getTemplateByRationID(ration.ID);
  77. if(template) {
  78. $("#createLocation").val(template.createLocation);
  79. let pcol = _.findIndex(this.setting.header,{dataCode:"position"});
  80. this.setting.header[pcol].visible = template.createLocation == 3?false:true;
  81. datas = _.cloneDeep(template.templateList);
  82. }
  83. }
  84. this.datas = datas;
  85. this.nodeChanged = false;//这里要恢复成false 应为调用gljObj.refresh() 方法也会进到这里来,这时节点应是没有改变的
  86. }
  87. sheetCommonObj.showData(this.sheet, this.setting,this.datas);
  88. this.sheet.setRowCount(this.datas.length);
  89. },
  90. onSheetValueChange:function (e,info) {
  91. let me = mbzm_obj;
  92. let selected = projectObj.project.mainTree.selected;
  93. let row = info.row, col = info.col;
  94. let dataCode = me.setting.header[col].dataCode;
  95. let recode = me.datas[row], value = info.newValue;
  96. if (info.newValue === undefined) {
  97. return;
  98. }
  99. if (value && !sheetCommonObj.checkData(col, me.setting, value)) {
  100. alert('输入的数据类型不对,请重新输入!');
  101. me.refreshSheetData();
  102. return;
  103. }
  104. if (dataCode === 'coe') {//默认为0,可输入数值,输入数值后,后面的工程量=混凝土子目工程量*系数。
  105. let rationQuantity = selected.data.quantity;
  106. rationQuantity = rationQuantity?scMathUtil.roundForObj(rationQuantity, getDecimal('ration.quantity')):0;
  107. value = scMathUtil.roundForObj(value, getDecimal('process'));
  108. recode["quantity"] = scMathUtil.roundForObj(rationQuantity * value, getDecimal('ration.quantity'))+"";
  109. }
  110. if (dataCode === 'quantity') {//定额默认显示为0,可输入数值,输入数值后,则清空前面的系数列
  111. value = scMathUtil.roundForObj(value, getDecimal('ration.quantity'))+"";
  112. recode["coe"] = "0";
  113. }
  114. recode[dataCode] = value;
  115. me.refreshSheetData();
  116. },
  117. updatePosition:function (recode) {
  118. let selection = this.sheet.getSelections()[0];
  119. let selectedItem =(this.datas[selection.row]);
  120. let updateField = $("#createLocation").val()==this.locateMap.INMEASURE?"billID":"fxID";
  121. if(selectedItem[updateField] == recode.ID) return;
  122. selectedItem[updateField] = recode.ID;
  123. if($("#createLocation").val()==this.locateMap.INMEASURE)selectedItem.billsLocation = recode.code;
  124. this.refreshSheetData();
  125. },
  126. applyTemplate:function () {//应用清单模板
  127. let selected = projectObj.project.mainTree.selected;
  128. let template = projectObj.project.ration_template.getTemplateByRationID(selected.data.ID);
  129. let createLocation = $("#createLocation").val();
  130. let rations = {update:[],create:[]},bills={update:[],create:[]};
  131. if(this.datas.length <= 0) return;
  132. for(let d of this.datas){
  133. if(gljUtil.isDef(d.quantity)&& parseFloat(d.quantity)>0){
  134. if(this.positionChecking(createLocation,d) == false){
  135. alert(`请选择${d.code}生成的清单位置`);
  136. return;
  137. }
  138. this.getNodeUpdateData(d,selected.data.ID,createLocation,rations,bills);
  139. }
  140. }
  141. let ration_template={type:ModuleNames.ration_template,data:{ID:template.ID, createLocation:createLocation, templateList:this.datas}};
  142. let data = {
  143. ration_template:ration_template,
  144. rations:rations,
  145. bills:bills
  146. };
  147. console.log(data);
  148. $.bootstrapLoading.start();
  149. CommonAjax.post('/ration/applyTemplate',data,function (result) {
  150. $.bootstrapLoading.end();
  151. let refreshNodes = projectObj.project.updateNodesCache(result.updateDatas);//更新要update的前端缓存,并返回要刷新的树节点
  152. //对于新插入的清单:
  153. if(result.billsResult.length > 0){
  154. }
  155. //对于新插入的定额
  156. console.log(result);
  157. })
  158. },
  159. positionChecking(type,data){//这个要之后再测试一下
  160. let validate = true;
  161. if(type == mbzm_obj.locateMap.INMEASURE){
  162. if(!_.isEmpty(data.billID)){
  163. let node = projectObj.project.mainTree.getNodeByID(data.billID);
  164. if(!node) validate = false;//ID有值,但是找不到,说明清单已经被删除
  165. }else if(_.isEmpty(data.billsLocation)){
  166. validate = false
  167. }
  168. }else {
  169. if(_.isEmpty(data.fxID)) {
  170. validate = false;
  171. }else {
  172. let node = projectObj.project.mainTree.getNodeByID(data.fxID);
  173. if(!node) validate = false;//ID有值,但是找不到,说明分项已经被删除
  174. }
  175. }
  176. return validate
  177. },
  178. getNodeUpdateData:function(data,referenceRationID,type,rations,bills){
  179. let quantity = this.getQuantity(data);//工程量要经过转换
  180. let mainRation = projectObj.project.mainTree.getNodeByID(referenceRationID);
  181. let billsID="";
  182. //先检查要更新的定额是否已经存在
  183. let ration = this.getExistRation(data,referenceRationID,type);
  184. if(ration) {//如果存在,则比较清耗量、工程量表达式是否一致
  185. let tem = this.getRationData(ration,data,quantity);//取更新信息
  186. if(tem){//如果不一致,则需要更新
  187. rations.update.push(tem);
  188. }
  189. //在定额存在的情况下,不用往下执行了
  190. return;
  191. }
  192. //定额不存在的情况下
  193. if(type == mbzm_obj.locateMap.AFTERRATION) {//如果是生成在主定额后面的位置
  194. this.createNewRationAfterMain(data,mainRation,quantity,rations);
  195. }
  196. if(type == mbzm_obj.locateMap.INMEASURE){//生成在措施项目下
  197. this.createNewRationInMeasure(data,mainRation,quantity,rations,bills);
  198. }else {
  199. this.createNewRationInFBFX(data,mainRation,quantity,rations,bills);
  200. }
  201. /*[
  202. {
  203. type:'ration',
  204. data:{
  205. projectID:1605,
  206. ID:"7b962fb0-1131-11e8-b3da-af725dadd7ae",
  207. name:'testRation'
  208. }
  209. },
  210. {
  211. type:'bills',
  212. data:{
  213. projectID:1605,
  214. ID:"af9f0081-1127-11e8-99a8-2fc02230b6e7",
  215. name:'安全文明施工专项费用123'
  216. }
  217. }
  218. ]*/
  219. },
  220. getRationData:function (ration,data,quantity) {
  221. let tem = {};
  222. if (ration.quantity + "" != quantity) tem.quantity = quantity;
  223. if (gljUtil.isDef(data.coe) && data.coe != "0") tem.quantityEXP = "MBGCL";
  224. if(!_.isEmpty(tem)) {
  225. tem.projectID = ration.projectID;
  226. tem.ID = ration.ID;
  227. return tem;
  228. }
  229. return null;
  230. },
  231. createNewRationAfterMain:function (data,mainRation,quantity,rations) {
  232. //生成新的定额
  233. let newID = uuid.v1();
  234. let serialNo = mainRation.data.serialNo+1;
  235. //如果已经有正要生成的定额,则取这个序号再加1
  236. if(rations.create.length > 0){
  237. serialNo = rations.create[rations.create.length -1].newData.serialNo + 1
  238. }
  239. let n_ration = this.createNewRationData(data,newID,mainRation.data.referenceRationID,mainRation.data.billsItemID,serialNo,quantity,mainRation.data.libID);
  240. rations.create.push(n_ration);
  241. //处理其它兄弟节点的序号
  242. let br = projectObj.project.Ration.getBillsSortRation();
  243. for(let i = mainRation.data.serialNo;i<br.length;i++){
  244. if(rations.update.length > 0){//如果update列表中有数据,要更新那里的序列号
  245. let u = _.find(rations.update,{'ID':br[i].ID});
  246. if(u){
  247. u.serialNo += 1;
  248. continue;
  249. }
  250. }
  251. rations.update.push({ID:br[i].ID,projectID:br[i].projectID,serialNo:br[i].serialNo+1})
  252. }
  253. },
  254. createNewRationInMeasure:function (data,mainRation,quantity,rations,bills) {
  255. let controller = projectObj.mainController;
  256. let billsID="";
  257. if(!_.isEmpty(data.billID)&&projectObj.project.mainTree.getNodeByID(data.billID)){
  258. billsID = data.billID;
  259. }else {//剩下的就是没找到的
  260. let rootNode = projectObj.project.Bills.getMeasureNode(controller);
  261. let leaveNodes = projectObj.mainController.tree.getLeavesNodes(rootNode.source);
  262. for(let n of leaveNodes){
  263. if (!(n.data.calcBase&&n.data.calcBase!="")&& n.data.code&&(n.data.code ==data.billsLocation||n.data.code.indexOf(data.billsLocation) != -1)){//没有使用基数计算的清单
  264. billsID = n.data.ID;
  265. break;
  266. }
  267. }
  268. if(billsID == ""){//还是没有找到的情况下,先查找是不是已经生成过了
  269. if(bills.create.length > 0){
  270. let t_b = _.find(bills.create,{"billsLocation":data.billsLocation});
  271. if(t_b) billsID = t_b.ID;
  272. }
  273. }
  274. if(billsID == ""){//也没有生成过的情况下,要自动生成清单
  275. let parentNode = projectObj.project.Bills.getAutoParentNode("措施费用");
  276. billsID = uuid.v1();
  277. let newBill = {
  278. ID:billsID,
  279. projectID: parseInt(projectObj.project.ID()),
  280. ParentID:parentNode.data.ID,
  281. NextSiblingID:-1,
  282. code:projectObj.project.Bills.newFormatCode(data.billsLocation),
  283. billsLibId:projectInfoObj.projectInfo.engineeringInfo.bill_lib[0].id,//projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib
  284. billsLocation : data.billsLocation//这个是用来在后端查找清单信息
  285. };
  286. let existB = projectObj.project.Bills.sameStdCodeBillsData(data.billsLocation);//对于多单位的清单
  287. if (existB) {
  288. newBill.unit = existB.unit;
  289. }
  290. //将这个节点的上一节点的NextSiblingID设置为这个新清单
  291. //先看有没有刚生成的清单,有的话直接修改最后一个清单的NextSiblingID即可
  292. let lastIndex = this.getLastIndex(bills.create,"ParentID",parentNode.data.ID);
  293. if(bills.create.length > 0 && lastIndex!=-1){
  294. bills.create[lastIndex].NextSiblingID = newBill.ID;
  295. }else if(parentNode.children.length > 0){//如果新生的没有找到的话,查看父节点下是否有子节点
  296. let pre = parentNode.children[parentNode.children.length-1];
  297. bills.update.push({ projectID:newBill.projectID,ID:pre.data.ID, NextSiblingID:newBill.ID});
  298. }
  299. bills.create.push(newBill);
  300. }
  301. }
  302. //生成定额
  303. let newID = uuid.v1();
  304. let serialNo = 1;
  305. serialNo = this.checkAndGetSerialNo(serialNo,billsID,rations);
  306. //先查看刚生成的定额中有没有相同父清单,有的话取最后的一个序列号加1
  307. let n_ration = this.createNewRationData(data,newID,mainRation.data.ID,billsID,serialNo,quantity,mainRation.data.libID);
  308. rations.create.push(n_ration);
  309. },
  310. createNewRationInFBFX:function (data,mainRation,quantity,rations,bills) {
  311. let billsID = "";
  312. let parentNode = projectObj.project.mainTree.getNodeByID(data.fxID);
  313. //分部分项这里,如果没选择位置,或者选择后又删除了,是无法到这一步的,所以不用像生成在清单那里做很多检查
  314. if(!_.isEmpty(data.fxID)&&parentNode){
  315. billsID = data.fxID;
  316. }
  317. if(billsID !=""){
  318. //生成定额
  319. let newID = uuid.v1();
  320. let serialNo = 1;
  321. serialNo = this.checkAndGetSerialNo(serialNo,billsID,rations);
  322. let n_ration = this.createNewRationData(data,newID,mainRation.data.ID,billsID,serialNo,quantity,mainRation.data.libID,true);
  323. rations.create.push(n_ration);
  324. }
  325. },
  326. getLastIndex:function (arrays,key,value) {
  327. let index = -1;
  328. for (let i = 0;i<arrays.length;i++) {
  329. if(arrays[i][key] == value){
  330. index = i;
  331. }
  332. }
  333. return index;
  334. },
  335. checkAndGetSerialNo:function (sNo,billsID,rations) {
  336. let serialNo = sNo;
  337. //先查看刚生成的定额中有没有相同父清单,有的话取最后的一个序列号加1
  338. let last_ration = this.getLastBrotherNewRation(billsID,rations.create);
  339. if(last_ration){
  340. serialNo = last_ration.serialNo +1;
  341. }else {
  342. let parentBillsNode = projectObj.project.mainTree.getNodeByID(billsID);
  343. if(parentBillsNode && parentBillsNode.children.length > 0){//如果能找到则说明已经存在的清单
  344. serialNo = parentBillsNode.children[parentBillsNode.children.length - 1].data.serialNo + 1
  345. }
  346. }
  347. return serialNo
  348. },
  349. getLastBrotherNewRation:function(billsItemID,rations){
  350. let newData = null;
  351. for(let tem of rations){
  352. if(tem.newData.billsItemID == billsItemID) newData = tem.newData;
  353. }
  354. return newData;
  355. },
  356. createNewRationData:function (data,newID,referenceRationID,billsID,serialNo,quantity,libID,isFBFX) {
  357. let newData = projectObj.project.Ration.getTempRationData(newID,billsID,serialNo,rationType.ration);
  358. newData.referenceRationID = referenceRationID;
  359. newData.quantity = quantity;
  360. newData.quantityEXP = gljUtil.isDef(data.coe) && data.coe != "0"?"MBGCL":quantity+"";
  361. let temRation = this.getDefaultRationCreateData(newData,data.code,libID,isFBFX);
  362. return temRation;
  363. },
  364. getDefaultRationCreateData:function(newData,code,libID,isFBFX){
  365. let itemQuery = {userID: userID, rationRepId: libID, code: code};
  366. let needInstall = false;
  367. if(projectObj.project.isInstall()) {//如果是安装工程,要看需不需要生成安装增加费
  368. needInstall = isFBFX;//在分部分项插入的定额才需要定额安装增加费
  369. }
  370. return{itemQuery:itemQuery,newData:newData,defaultLibID: rationLibObj.getDefaultStdRationLibID(),calQuantity:false,brUpdate:[],needInstall:needInstall}
  371. },
  372. getQuantity:function (data) {//取最新的消耗量,需经过转换
  373. if(data.unit){
  374. let times = parseInt(data.unit);
  375. if(!isNaN(times)){
  376. return scMathUtil.roundForObj(parseFloat(data.quantity)/times,getDecimal("ration.quantity"))+""
  377. }
  378. }
  379. return data.quantity
  380. },
  381. getExistRation:function (data,referenceRationID,type) {
  382. let temRation = null;
  383. //先检查要更新的定额是否已经存在
  384. let rations =_.filter(projectObj.project.Ration.datas,{'referenceRationID':referenceRationID,'code':data.code});
  385. for(let r of rations){
  386. if(type == mbzm_obj.locateMap.AFTERRATION){//如果是生成在主定额后面的位置
  387. let mainRationNode = projectObj.project.mainTree.getNodeByID(referenceRationID);
  388. if(r.billsItemID == mainRationNode.data.billsItemID){//如果清单ID相同, 说明是兄弟节点,位置相同
  389. temRation = r;
  390. break;
  391. }
  392. }
  393. let billsNode = projectObj.project.mainTree.getNodeByID(r.billsItemID);
  394. if(billsNode){//将父清单与要生成的清单比较,看是否一致
  395. if(type == mbzm_obj.locateMap.INMEASURE && billsNode.data.type ==billType.BILL){
  396. if(!_.isEmpty(data.billID)){
  397. //说明生成位置已经有定额了,只需更新消耗量就好
  398. if(data.billID == r.billsItemID){
  399. temRation = r;
  400. break;
  401. }
  402. }else if(!_.isEmpty(data.billsLocation)){//按清单编号到找对应的位置
  403. if(billsNode.data.code && billsNode.data.code.indexOf(data.billsLocation)!=-1) {
  404. temRation = r;
  405. break;
  406. }
  407. }
  408. }else if(type == mbzm_obj.locateMap.INFBFX && (billsNode.data.type ==billType.FX||billsNode.data.type ==billType.BX)){
  409. if(!_.isEmpty(data.fxID) && data.fxID == r.billsItemID){//分项、补项下有对应的定额
  410. temRation = r;
  411. break;
  412. }
  413. }
  414. }
  415. }
  416. return temRation;
  417. }
  418. };
  419. $('#createLocation').change(function(){
  420. let me = mbzm_obj;
  421. let pcol = _.findIndex(me.setting.header,{dataCode:"position"});
  422. me.setting.header[pcol].visible = $(this).val() == mbzm_obj.locateMap.AFTERRATION?false:true;
  423. me.refreshSheetData();
  424. });
  425. $('#next_mbzm').click(function () {
  426. let mainSheet = projectObj.mainSpread.getActiveSheet();
  427. let selection = mainSheet.getSelections()[0];
  428. let node = projectObj.project.mainTree.selected;
  429. let index = node.serialNo();
  430. let next = null;
  431. for(let i = index+1;i< projectObj.project.mainTree.items.length;i++){
  432. let temNode = projectObj.project.mainTree.items[i];
  433. if(temNode && temNode.sourceType == ModuleNames.ration){
  434. let template = projectObj.project.ration_template.getTemplateByRationID(temNode.data.ID);
  435. if(template) {
  436. next = temNode;
  437. break;
  438. }
  439. }
  440. }
  441. if(next){
  442. let row = next.serialNo();
  443. let col = selection.col?selection.col:0;
  444. mainSheet.setSelection(row, col, selection.rowCount, selection.colCount);
  445. projectObj.mainController.setTreeSelected(next);
  446. mainSheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
  447. }
  448. });
  449. $('#apply_mbzm').click(function () {
  450. mbzm_obj.applyTemplate();
  451. });