exportSEIInterface.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /**
  2. * Created by zhang on 2019/5/20.
  3. */
  4. let exportUtil = {
  5. setEngineerPriceIndex:function (tender,projectData) {
  6. let priceIndex = {
  7. name:"工程造价指标",
  8. attrs:[],
  9. children:[],
  10. };
  11. let fixMap = {};
  12. let buildingArea = this.getBuildArea(tender.property.engineerFeatures); //tender.property.projectFeature?getItemValueBykey(tender.property.projectFeature,"buildingArea"):1;//建筑面积
  13. for(let b of projectData.bills){
  14. if(b.flags && b.flags.length > 0){
  15. let f = _.find(b.flags,{"fieldName":"fixed"});
  16. if(f) fixMap[f.flag] = this.getTotalFee(b);
  17. }
  18. }
  19. //计算其他组织措施费 = 施工组织措施项目下的子项,除了 安全文明施工费、建设工程竣工档案编制费以外的项
  20. let CONSTRUCTION_ORGANIZATION = fixMap[fixedFlag.CONSTRUCTION_ORGANIZATION]?fixMap[fixedFlag.CONSTRUCTION_ORGANIZATION]:0;
  21. let SAFETY_CONSTRUCTION = fixMap[fixedFlag.SAFETY_CONSTRUCTION]?fixMap[fixedFlag.SAFETY_CONSTRUCTION]:0;
  22. let PROJECT_COMPLETE_ARCH_FEE = fixMap[fixedFlag.PROJECT_COMPLETE_ARCH_FEE]? fixMap[fixedFlag.PROJECT_COMPLETE_ARCH_FEE]:0;
  23. let other_org_fee = CONSTRUCTION_ORGANIZATION - SAFETY_CONSTRUCTION - PROJECT_COMPLETE_ARCH_FEE;
  24. other_org_fee = other_org_fee >0 ?other_org_fee:0;
  25. let engineerCost = fixMap[fixedFlag.ENGINEERINGCOST]?fixMap[fixedFlag.ENGINEERINGCOST]:1;
  26. priceIndex.children.push(this.getFlag("分部分项工程费",fixMap[fixedFlag.SUB_ENGINERRING],engineerCost,buildingArea));
  27. priceIndex.children.push(this.getFlag("技术措施费",fixMap[fixedFlag.CONSTRUCTION_TECH],engineerCost,buildingArea));
  28. priceIndex.children.push(this.getFlag("安全文明施工费",fixMap[fixedFlag.SAFETY_CONSTRUCTION],engineerCost,buildingArea));
  29. priceIndex.children.push(this.getFlag("建设工程竣工档案编制费",fixMap[fixedFlag.PROJECT_COMPLETE_ARCH_FEE],engineerCost,buildingArea));
  30. priceIndex.children.push(this.getFlag("其他组织措施费",other_org_fee,engineerCost,buildingArea));
  31. priceIndex.children.push(this.getFlag("暂列金额",fixMap[fixedFlag.PROVISIONAL],engineerCost,buildingArea));
  32. priceIndex.children.push(this.getFlag("专业工程暂估价",fixMap[fixedFlag.ENGINEERING_ESITIMATE],engineerCost,buildingArea));
  33. priceIndex.children.push(this.getFlag("计日工",fixMap[fixedFlag.DAYWORK],engineerCost,buildingArea));
  34. priceIndex.children.push(this.getFlag("总承包服务费",fixMap[fixedFlag.TURN_KEY_CONTRACT],engineerCost,buildingArea));
  35. priceIndex.children.push(this.getFlag("索赔与现场签证",fixMap[fixedFlag.CLAIM_VISA],engineerCost,buildingArea));
  36. priceIndex.children.push(this.getFlag("规费",fixMap[fixedFlag.CHARGE],engineerCost,buildingArea));
  37. priceIndex.children.push(this.getFlag("税金",fixMap[fixedFlag.TAX],engineerCost,buildingArea));
  38. priceIndex.children.push(this.getFlag("工程造价",fixMap[fixedFlag.ENGINEERINGCOST],engineerCost,buildingArea));
  39. return priceIndex;
  40. },
  41. getTotalFee:function (b) {
  42. let total = 0;
  43. if(b.fees && b.fees.length > 0){
  44. let common = _.find(b.fees,{"fieldName":"common"});
  45. if(common) total = scMathUtil.roundForObj(common.totalFee,getDecimal("bills.totalPrice"))
  46. }
  47. return total;
  48. },
  49. getFlag: function (name,totalCost,engineerCost,buildingArea) {
  50. totalCost = totalCost?totalCost:0;
  51. let flag = {
  52. name:name,
  53. attrs:[
  54. {name: "金额", value: scMathUtil.roundToString(totalCost,3)},
  55. {name: "单方造价", value: scMathUtil.roundToString(exportUtil.calcUnitB(totalCost,buildingArea),2)},
  56. {name: "占造价比例", value: scMathUtil.roundToString(totalCost/engineerCost * 100,2)},
  57. ],
  58. };
  59. return flag;
  60. },
  61. getBuildArea:function (features) {
  62. if(features){
  63. let areas = [];
  64. for(let f of features){
  65. if(f.index == true && f.value && f.value !=="" && IsNumber(f.value)) areas.push(f.value);
  66. }
  67. return _.isEmpty(areas)?1:areas;
  68. }
  69. return 1
  70. },
  71. calcUnitB:function (total,building,coe,decimal = 3) {
  72. if(Array.isArray(building)){
  73. for(let b of building){
  74. total = scMathUtil.roundForObj(total/b,6);
  75. }
  76. }else {
  77. total = scMathUtil.roundForObj(total/building,6);
  78. }
  79. coe = coe?coe:1;
  80. return scMathUtil.roundForObj(total*coe,decimal);
  81. },
  82. calUnitWidthCoe:function (total,noNeedCoe) {
  83. let areas = exportUtil.getBuildArea(projectObj.project.property.engineerFeatures);
  84. let f = _.find(projectObj.project.property.engineerFeatures,{index:true});
  85. return f && noNeedCoe!==true?exportUtil.calcUnitB(total,areas,f.coe):exportUtil.calcUnitB(total,areas);
  86. },
  87. getIndexBills:function (bills) {
  88. let parentMap = {},datas = [],totalCost = 0;
  89. let FBFX_b = null,teh_b = null,costNode=null;
  90. for(let b of bills) {
  91. parentMap[b.ParentID] ? parentMap[b.ParentID].push(b) : parentMap[b.ParentID] = [b];//有添加,无则生成
  92. if(b.flags && b.flags.length > 0){
  93. let f = _.find(b.flags,{"fieldName":"fixed"});
  94. if(!f) continue;
  95. if(f.flag == fixedFlag.SUB_ENGINERRING) FBFX_b = b;//过滤出分部分项工程;
  96. if(f.flag == fixedFlag.CONSTRUCTION_TECH) teh_b = b;//过滤出技术措施项目;
  97. if(f.flag == fixedFlag.ENGINEERINGCOST) costNode = b;//过滤出技术措施项目;
  98. }
  99. }
  100. if(FBFX_b) getChildren(FBFX_b,parentMap,datas);
  101. if(teh_b) getChildren(teh_b,parentMap,datas);
  102. if(costNode) totalCost = exportUtil.getTotalFee(costNode);
  103. for(let td of datas){
  104. if(parentMap[td.ID]){
  105. td.economicType = "";
  106. td.quantityIndexType = "";
  107. td.quantityIndexUnit = "";
  108. td.quantityIndexCoe = "";
  109. }
  110. }
  111. return [datas,totalCost];
  112. function getChildren(d,map,arr) {
  113. let tem = {
  114. ID:d.ID,
  115. ParentID:d.ParentID,
  116. code:d.code,
  117. name:d.name,
  118. unit:d.unit,
  119. quantity:d.quantity,
  120. totalFee:exportUtil.getTotalFee(d),
  121. economicType:d.economicType,
  122. quantityIndexType:d.quantityIndexType,
  123. quantityIndexUnit:d.quantityIndexUnit,
  124. quantityIndexCoe:d.quantityIndexCoe,
  125. };
  126. arr.push(tem);
  127. if(map[d.ID]){
  128. for(let s of map[d.ID]){
  129. getChildren(s,map,arr)
  130. }
  131. }
  132. }
  133. }
  134. };
  135. async function exportSEI(projectID) {
  136. let tenderProjects = [];
  137. let result = await ajaxPost("/project/getSEIProjects",{projectID:projectID});
  138. let pr = new SCComponent.InitProgressBar($('#progress'), $('#progress-title'), $('#progress-content'), $('#progressBar'));
  139. pr.start('导出数据接口', '正在导出文件,请稍候……');
  140. console.log(result);
  141. let project = getProject(result);
  142. await prepareTenderDatas(tenderProjects,project);
  143. toXml(project);
  144. pr.end();
  145. function getProject(orignal) {//取建设项目信息
  146. let basicInformation = getBaseInfo(orignal);
  147. let project = {
  148. name: "建设项目",
  149. attrs: [
  150. {name: "项目名称", value: orignal.name},
  151. {name:"建设单位",value:getItemValueBykey(basicInformation.items,"constructionUnit")},
  152. {name:"施工单位",value:getItemValueBykey(basicInformation.items,"buildingUnit")},
  153. {name: "标准名称", value: "重庆市建设工程造价指标采集标准(清单计价)"},
  154. {name: "标准版本号", value: "1.1"}
  155. ],
  156. basicInformation:basicInformation,
  157. children:[]
  158. };
  159. initAtts(project.attrs);
  160. for(let c of orignal.children){
  161. project.children.push(getEngineering(c));
  162. }
  163. return project;
  164. }
  165. function getEngineering(source){
  166. let engineer = {
  167. name:"单项工程",
  168. attrs:[
  169. {name: "名称", value: source.name}
  170. ],
  171. children:[]
  172. };
  173. for(let c of source.children){
  174. let tenderProject = getTender(c);
  175. engineer.children.push(tenderProject);
  176. tenderProjects.push(tenderProject);
  177. }
  178. return engineer
  179. };
  180. function getTender(source) {
  181. let tender = {
  182. ID:source.ID,
  183. name:"单位工程",
  184. attrs:[
  185. {name: "名称", value: source.name}
  186. ],
  187. children:[],
  188. valuationType:source.property.valuationType,
  189. taxType:source.property.taxType,
  190. property:source.property
  191. };
  192. return tender;
  193. }
  194. async function prepareTenderDatas(tenders,project) {
  195. for(let t of tenders){
  196. await setTenderData(t,project);
  197. }
  198. }
  199. async function setTenderData(tender,project) {
  200. let projectData = await ajaxPost("/project/loadSEIProjectData",{projectID:tender.ID});
  201. tender.children.push(setEngineerInfo(tender));//设置工程信息
  202. tender.children.push(setEngineerFeature(tender));//设置工程特征
  203. tender.children.push(setEngineerIndex(tender,projectData));
  204. tender.children.push(await setGLJSummy(tender,projectData));
  205. //
  206. }
  207. function setEngineerIndex(tender,projectData) {//设置工程指标
  208. let index = {
  209. name:"工程指标",
  210. attrs:[],
  211. children:[],
  212. };
  213. let indexName = tender.property.indexName?tender.property.indexName:"建筑工程";
  214. index.children.push(exportUtil.setEngineerPriceIndex(tender,projectData));
  215. index.children.push(setEngineerEcoIndex(tender,projectData,indexName));
  216. index.children.push(setMainMaterialIndex(tender,projectData,indexName));
  217. index.children.push(setQuantityIndex(tender,projectData,indexName));
  218. return index;
  219. function setMainMaterialIndex(tender,projectData,indexName){
  220. let mainIndex = {
  221. name:`${indexName}工料指标`,
  222. attrs:[],
  223. children:[]
  224. };
  225. if(projectData) gljUtil.calcProjectGLJQuantity(projectData.projectGLJs,projectData.ration_gljs,projectData.rations,projectData.bills,getDecimal("glj.quantity"),_,scMathUtil);
  226. let materials = indexObj.getMainMaterialDatas(tender.property.materials,projectData.projectGLJs,tender.property.calcOptions,tender.property.decimal,false,_,scMathUtil);
  227. for(let m of materials){
  228. mainIndex.children.push(getMaterial(m))
  229. }
  230. let index = {
  231. name:"主要工料价格及消耗量指标",
  232. attrs:[],
  233. children:[mainIndex]
  234. };
  235. return index;
  236. function getMaterial(m) {
  237. let material = {
  238. name:m.name,
  239. attrs:[
  240. {name:"综合单价",value:scMathUtil.roundToString(m.unitPrice,2)},
  241. {name:"数量",value:scMathUtil.roundToString(m.quantity,2)},
  242. {name:"单方指标",value:scMathUtil.roundToString(m.unitIndex,3)},
  243. {name:"单位",value:m.unit}
  244. ]
  245. };
  246. return material;
  247. }
  248. }
  249. function setQuantityIndex(tender,projectData,indexName) {
  250. let quantityIndex = {
  251. name:`${indexName}量指标`,
  252. attrs:[],
  253. children:[]
  254. };
  255. let quantities = indexObj.getQuantityDatas(tender.property.mainQuantities,projectData.bills);
  256. for(let q of quantities){
  257. quantityIndex.children.push(getQuantity(q));
  258. }
  259. let index = {
  260. name:`主要工程量指标`,
  261. attrs:[],
  262. children:[quantityIndex]
  263. };
  264. return index;
  265. function getQuantity(q) {
  266. let quantity = {
  267. name:q.name,
  268. attrs:[
  269. {name:"工程量指标",value:scMathUtil.roundToString(q.quantity,3)},
  270. {name:"单位",value:q.unit}
  271. ]
  272. };
  273. return quantity;
  274. }
  275. }
  276. function setEngineerEcoIndex(tender,projectData,indexName) {
  277. let ecoIndex = {
  278. name:`${indexName}经济指标`,
  279. attrs:[],
  280. children:[]
  281. };
  282. let economicDatas = indexObj.getEconomicDatas(tender.property.economics,projectData.bills);
  283. for(let e of economicDatas){
  284. ecoIndex.children.push(getEco(e))
  285. }
  286. let index = {
  287. name:`工程经济指标`,
  288. attrs:[],
  289. children:[ecoIndex]
  290. };
  291. return index;
  292. function getEco(e) {
  293. let eco = {
  294. name:e.name,
  295. attrs:[
  296. {name:"综合合价",value:scMathUtil.roundToString(e.cost,2)},
  297. {name:"单方指标",value:scMathUtil.roundToString(e.unitCost,2)},
  298. {name:"占造价比例",value:scMathUtil.roundToString(e.per,2)}
  299. ]
  300. };
  301. return eco;
  302. }
  303. }
  304. }
  305. async function setGLJSummy(tender,projectData) {
  306. let gljs = {
  307. name:"人材机汇总",
  308. attrs:[],
  309. children:[]
  310. };
  311. setGLJDetail(projectData,tender.property,gljs);
  312. return gljs;
  313. }
  314. function setGLJDetail(projectData,property,gljs) {
  315. if(projectData){
  316. gljUtil.calcProjectGLJQuantity(projectData.projectGLJs,projectData.ration_gljs,projectData.rations,projectData.bills,getDecimal("glj.quantity"),_,scMathUtil);
  317. }
  318. for(let g of projectData.projectGLJs.gljList) {
  319. if (!g.quantity || g.quantity == "") continue;
  320. g.marketPrice = gljUtil.getMarketPrice(g,projectData.projectGLJs,property.calcOptions,property.decimal,false,_,scMathUtil);
  321. gljs.children.push(setEachGLJ(g));
  322. }
  323. }
  324. function setEachGLJ(source){
  325. let g = {
  326. name:"人材机",
  327. attrs:[
  328. {name: "代码", value: source.code},
  329. {name: "名称", value: source.name},
  330. {name: "规格型号", value: source.specs},
  331. {name: "单位", value: source.unit},
  332. {name: "市场单价", value: source.marketPrice},
  333. {name: "数量", value: source.quantity},
  334. {name: "类型", value: source.type},
  335. {name: "产地", value: source.originPlace},
  336. {name: "厂家", value: source.vender},
  337. {name: "备注", value: source.remark}
  338. ]
  339. };
  340. return g;
  341. }
  342. function setEngineerInfo(tender) {//设置工程信息
  343. let infos = tender.property.engineerInfos?tender.property.engineerInfos:[];
  344. let info = {
  345. name:"工程信息",
  346. attrs:[
  347. {name:"造价编制单位",value:getItemValueByDispName(infos,"造价编制单位")},
  348. {name:"造价审核单位",value:getItemValueByDispName(infos,"造价审核单位")},
  349. {name:"项目负责人",value:getItemValueByDispName(infos,"项目负责人")},
  350. {name:"施工单位编制人员",value:getItemValueByDispName(infos,"施工单位编制人员")},
  351. {name:"编制人员",value:getItemValueByDispName(infos,"编制人员")},
  352. {name:"审核人员",value:getItemValueByDispName(infos,"审核人员")},
  353. {name:"开工日期",value:getItemValueByDispName(infos,"开工日期")},
  354. {name:"竣工日期",value:getItemValueByDispName(infos,"竣工日期")},
  355. {name:"工程地点",value:getItemValueByDispName(infos,"工程地点")},
  356. {name:"工程类型",value:getItemValueByDispName(infos,"工程类型")},
  357. {name:"合同价类型",value:getItemValueByDispName(infos,"合同价类型")},
  358. {name:"造价类型",value:getItemValueByDispName(infos,"造价类型")},
  359. {name:"计价方式及依据",value:getItemValueByDispName(infos,"计价方式及依据")},
  360. {name:"工程类别",value:getItemValueByDispName(infos,"工程类别")},
  361. {name:"编制日期",value:getItemValueByDispName(infos,"编制日期")},
  362. {name:"审查日期",value:getItemValueByDispName(infos,"审查日期")}
  363. ]
  364. };
  365. initAtts(info.attrs);
  366. return info;
  367. }
  368. function setEngineerFeature(tender) {
  369. let fea = {
  370. name:"工程特征",
  371. attrs:[],
  372. children:[]
  373. };
  374. fea.children.push(setIndexName(tender));
  375. return fea;
  376. function setIndexName(tender) {
  377. let indexName = {
  378. name:tender.property.indexName?tender.property.indexName:"建筑工程",
  379. attrs:[],
  380. children:[]
  381. };
  382. setFeatures(tender,indexName.children);
  383. return indexName
  384. }
  385. function setFeatures(tender,arr) {
  386. let features = tender.property.engineerFeatures?tender.property.engineerFeatures:[];
  387. let parentMap = _.groupBy(features,"ParentID");
  388. let rootNodes = parentMap["-1"]?parentMap["-1"]:parentMap[null];
  389. for(let r of rootNodes){
  390. arr.push(getFeatrue(r,parentMap))
  391. }
  392. }
  393. function getFeatrue(node,parentMap){
  394. if(parentMap[node.ID]){//如果有子节点,那么它就是一个节点
  395. let tem = {
  396. name:node.name.replace("*",""),
  397. attrs:[],
  398. children:[]
  399. };
  400. for(let s of parentMap[node.ID]){
  401. let f = getFeatrue(s,parentMap);
  402. f.children?tem.children.push(f):tem.attrs.push(f);//如果有children这个属性,则返回的是一个节点,如果没有,则返回的是一个属性
  403. }
  404. return tem;
  405. }else {//如果没有子节点,那么它就是父节点的一个属性
  406. return {name:node.name.replace("*",""),value:node.value};
  407. }
  408. }
  409. }
  410. function getBaseInfo(project){
  411. let basicInformation = {items:[]};
  412. let tem = null;
  413. if(project.property&&project.property.basicInformation) tem =_.find(project.property.basicInformation,{"key":"basicInfo"});
  414. if(tem) basicInformation = tem;
  415. return basicInformation;
  416. }
  417. function getItemValueBykey(items,key) {
  418. let item = _.find(items,{"key":key});
  419. if(item) return item.value;
  420. return ""
  421. }
  422. function getItemValueByDispName(items,dispName) {
  423. let item = _.find(items,{"dispName":dispName});
  424. if(item) return item.value;
  425. return ""
  426. }
  427. function initAtts(arrs) {
  428. _.remove(arrs,function (item) {
  429. return item.required == false && _.isEmpty(item.value)
  430. })
  431. }
  432. //开始标签
  433. function startTag(ele) {
  434. let rst = `<${ele.name}`;
  435. for (let attr of ele.attrs) {
  436. rst += ` ${attr.name}="${ attr.value!=undefined&&attr.value!= null?attr.value:""}"`;
  437. }
  438. rst += ele.children&&ele.children.length > 0 ? '>' : '/>';
  439. return rst;
  440. }
  441. //结束标签
  442. function endTag(ele) {
  443. return `</${ele.name}>`;
  444. }
  445. //拼接成xml字符串
  446. function toXMLStr(eles) {
  447. let rst = '';
  448. for (let ele of eles) {
  449. rst += startTag(ele);
  450. if (ele.children&& ele.children.length > 0) {
  451. rst += toXMLStr(ele.children);
  452. rst += endTag(ele);
  453. }
  454. }
  455. return rst;
  456. }
  457. //格式化xml字符串
  458. function formatXml(text) {
  459. //去掉多余的空格
  460. text = '\n' + text.replace(/>\s*?</g, ">\n<");
  461. //调整格式
  462. let rgx = /\n(<(([^\?]).+?)(?:\s|\s*?>|\s*?(\/)>)(?:.*?(?:(?:(\/)>)|(?:<(\/)\2>)))?)/mg;
  463. let nodeStack = [];
  464. let output = text.replace(rgx, function($0, all, name, isBegin, isCloseFull1, isCloseFull2, isFull1, isFull2){
  465. let isClosed = (isCloseFull1 === '/') || (isCloseFull2 === '/' ) || (isFull1 === '/') || (isFull2 === '/');
  466. let prefix = '';
  467. if (isBegin === '!') {
  468. prefix = getPrefix(nodeStack.length);
  469. } else {
  470. if (isBegin !== '/') {
  471. prefix = getPrefix(nodeStack.length);
  472. if (!isClosed) {
  473. nodeStack.push(name);
  474. }
  475. } else {
  476. nodeStack.pop();
  477. prefix = getPrefix(nodeStack.length);
  478. }
  479. }
  480. let ret = '\n' + prefix + all;
  481. return ret;
  482. });
  483. let outputText = output.substring(1);
  484. return outputText;
  485. function getPrefix(prefixIndex) {
  486. let span = ' ';
  487. let output = [];
  488. for (let i = 0 ; i < prefixIndex; ++i) {
  489. output.push(span);
  490. }
  491. return output.join('');
  492. }
  493. }
  494. /*
  495. * 导出数据
  496. * @param {Number}tenderID(当前界面的单位工程ID,后台根据这个单位工程,根据导出粒度去找其建设项目下相关数据)
  497. * @return {void}
  498. * */
  499. function toXml(eleData) {
  500. //转换成xml字符串
  501. let xmlStr = toXMLStr([eleData]);
  502. //加上xml声明
  503. xmlStr = `<?xml version="1.0" encoding="utf-8"?>${xmlStr}`;
  504. //格式化
  505. xmlStr = formatXml(xmlStr);
  506. let blob = new Blob([xmlStr], {type: 'text/plain;charset=utf-8'});
  507. saveAs(blob, '经济指标.ZBF');
  508. }
  509. }
  510. $(function () {
  511. $("#SEIMenu").click(async function () {
  512. await exportSEI(projectObj.project.property.rootProjectID);
  513. $("#exportMenu").removeClass("show");
  514. })
  515. });