exportStandardInterface.js 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Zhong
  6. * @date 2019/3/15
  7. * @version
  8. */
  9. /*
  10. * 数据标准接口
  11. * 导出符合标准接口要求的xml
  12. * */
  13. const XMLStandard = (function () {
  14. //属性类型
  15. const TYPE = {
  16. DATE: 1, //日期类型YYYY-MM-DD
  17. DATE_TIME: 2, //日期类型YYY-MM-DDTHH:mm:ss
  18. INT: 3, //整数类型
  19. DECIMAL: 4, //数值类型,不限制小数位数
  20. NUM2: 5, //数值类型2:最多两位小数
  21. BOOL: 6 //布尔型
  22. };
  23. const WHITE_SPACE = {
  24. COLLAPSE: 1 //移除所有空白字符(换行、回车、空格以及制表符会被替换为空格,开头和结尾的空格会被移除,而多个连续的空格会被缩减为一个单一的空格)
  25. };
  26. /*
  27. * 标准文件中的约束(唯一性)
  28. * path为'.//'时,路径为:当前上下文中一级或多级深度
  29. * path为'a/b'时,路径为: 当前上下文a节点下节点b
  30. * */
  31. const CONSTRAINTS = {
  32. //建设项目上下文的约束
  33. PROJECT: [
  34. {path: './/', selector: '单项工程', field: '编号'}, //建设项目下所有单项工程,编号唯一
  35. {path: './/', selector: '单位工程', field: '编号'}, //建设项目下所有单位工程,编号唯一
  36. ],
  37. //单位工程上下文的约束
  38. TENDER: [
  39. {path: './/', selector: '清单项目', field: '项目编码'}, //单位工程下所有清单项目,项目编码唯一
  40. {path: './/', selector: '公式计算措施项', field: '序号'}, //单位工程下所有公式措施项,序号唯一
  41. {path: './/', selector: '人材机', field: '代码'}, //单位工程下所有人材机,代码唯一
  42. {path: './/', selector: '暂列金额明细', field: '编号'}, //单位工程下所有暂列金额明细,编号唯一
  43. {path: './/', selector: '专业工程暂估明细', field: '编号'}, //单位工程下所有专业工程暂估明细,编号唯一
  44. {path: './/', selector: '总承包服务费费用项', field: '编号'}, //单位工程下所有总承包服务费费用项,编号唯一
  45. {path: '其他项目清单/计日工/人工', selector: '计日工项目', field: '编号'}, //单位工程/其他项目清单/计日工/人工下所有计日工项目,编号唯一
  46. {path: '其他项目清单/计日工/材料', selector: '计日工项目', field: '编号'}, //单位工程/其他项目清单/计日工/材料下所有计日工项目,编号唯一
  47. {path: '其他项目清单/计日工/施工机械', selector: '计日工项目', field: '编号'}, //单位工程/其他项目清单/计日工/施工机械下所有计日工项目,编号唯一
  48. {path: './/', selector: '其他列项', field: '序号'}, //单位工程下所有其他列项,序号唯一
  49. {path: './/', selector: '费用项', field: '序号'}, //单位工程下所有费用项,序号唯一
  50. ]
  51. };
  52. /*
  53. * 唯一性约束检查
  54. * 无法在创建节点时就检查,需要形成完整的数据后检查
  55. * @param{Object}element(节点) {Array}constraints(约束数据)
  56. * */
  57. /*
  58. * 检查
  59. * 创建节点时检查节点的数据
  60. * 1.长度限制minLen,maxLen
  61. * 2.值的限制,固定范围:enumeration
  62. * @param {Array}datas(需要检查的属性数据)
  63. * @return {Array}没通过的属性
  64. * */
  65. function check(datas) {
  66. let rst = [];
  67. let dateReg = /([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8])))/;
  68. for (let data of datas) {
  69. data.value = typeof data.value === 'undefined' || data.value === null ? '' : data.value.toString();
  70. if (data.whiteSpace && data.whiteSpace === WHITE_SPACE.COLLAPSE) {
  71. data.value = data.value.replace(/[\r,\n,\t]/g, ' ');
  72. data.value = data.value.trim();
  73. data.value = data.value.replace(/\s{1,}/g, ' ');
  74. }
  75. if (!data.value && !data.minLen && !data.enumeration) { //值为空,且没有限制最小字符数,且没有限制值,则跳过
  76. continue;
  77. }
  78. if (data.minLen && data.value.length < data.minLen){
  79. rst.push(`“${data.name}”字符数不可小于${data.minLen}个`);
  80. } else if (data.maxLen && data.value.length > data.maxLen) {
  81. rst.push(`“${data.name}”字符数不可大于${data.maxLen}个`);
  82. } else if (data.enumeration && !data.enumeration.includes(data.value)) {
  83. rst.push(`“${data.name}”只能从“${data.enumeration.join(';')}”中选择`);
  84. } else if (data.type && data.type === TYPE.DATE && !dateReg.test(data.value)) {
  85. rst.push(`“${data.name}”日期格式必须是YYYY-MM-DD`);
  86. } else if (data.type && data.type === TYPE.INT && !Number.isInteger(parseFloat(data.value))) {
  87. rst.push(`“${data.name}”必须为整数`);
  88. } else if (data.type && data.type === TYPE.DECIMAL && isNaN(parseFloat(data.value))) {
  89. rst.push(`“${data.name}”必须为数值`)
  90. } else if (data.type && data.type === TYPE.NUM2) {
  91. let v = parseFloat(data.value);
  92. if (isNaN(v)) {
  93. rst.push(`“${data.name}”必须为数值`);
  94. } else if (data.value.split('.')[1].length > 2){
  95. rst.push(`“${data.name}”小数位数不得多于两位`);
  96. }
  97. } else if (data.type && data.type === TYPE.BOOL && !['true', 'false'].includes(data.value.toString())) {
  98. }
  99. }
  100. return rst;
  101. }
  102. //从fees数组中获取相关费用
  103. function getFee(fees, feeFields) {
  104. let fields = feeFields.split('.');
  105. let fee = fees.find(data => data.feeName === fields[0]);
  106. if (fee) {
  107. return 0;
  108. }
  109. return fee[fields[1]] || 0;
  110. }
  111. //造成导出失败
  112. let failList = [];
  113. /*
  114. * 定义不设置一个Node方法统一进入的原因:模板化比较直观,不分开定义节点的话,调用传参也很麻烦而且不直观。
  115. * 一个节点对应一个构造方法,方便其他版本开发、接收的人看起来更直观
  116. * @param {String}name(节点名) {Array}attrs(节点属性数据)
  117. * @return {void}
  118. * */
  119. function element(name, attrs) {
  120. this.element = name;
  121. this.attrs = attrs;
  122. this.children = [];
  123. this.fail = check(attrs);
  124. for (let fail of this.fail) {
  125. failList.push(`${name}-${fail}`);
  126. }
  127. }
  128. //根据字段获取基本信息、工程特征
  129. function getValueByKey(data, key) {
  130. for (let d of data) {
  131. if (d.key === key) {
  132. return d.value;
  133. }
  134. if (d.items && d.items.length > 0) {
  135. let findData = d.items.find(x => x.key === key);
  136. if (findData) {
  137. return findData.value;
  138. }
  139. }
  140. }
  141. return '';
  142. }
  143. //建设项目定义
  144. //source:来源数据
  145. function Project(source) {
  146. let attrs = [
  147. {name: '项目编号', value: getValueByKey(source.basicInformation, 'projNumber'), minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  148. {name: '项目名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  149. {name: '建设单位', value: getValueByKey(source.basicInformation, 'constructionUnit')},
  150. {name: '标准版本号', value: '3.2.2'},
  151. {name: '标准名称', value: '重庆造价软件数据交换标准(清单计价)'},
  152. {name: '文件类型', value: getValueByKey(source.basicInformation, 'fileKind'), enumeration: ['招标', '投标', '控制价', '结算', '其他']},
  153. {name: '计税方法', value: 'todo'},
  154. ];
  155. element.call(this, '标段', attrs);
  156. }
  157. //项目信息定义
  158. function ProjectInfo(source) {
  159. let attrs = [
  160. {name: '工程规模', value: getValueByKey(source.basicInformation, 'projectScale')},
  161. {name: '工程所在地', value: getValueByKey(source.basicInformation, 'projLocation')},
  162. {name: '工程地址', value: getValueByKey(source.basicInformation, 'projAddress')},
  163. {name: '施工单位', value: getValueByKey(source.basicInformation, 'buildingUnit')},
  164. {name: '编制单位', value: getValueByKey(source.basicInformation, 'establishmentUnit')},
  165. {name: '审核单位', value: getValueByKey(source.basicInformation, 'auditUnit')},
  166. {name: '编制人', value: getValueByKey(source.basicInformation, 'buildingUnitAuthor')},
  167. {name: '审核人', value: 'todo'},
  168. {name: '开工日期', value: getValueByKey(source.basicInformation, 'commencementDate'), type: TYPE.DATE},
  169. {name: '竣工日期', value: getValueByKey(source.basicInformation, 'completionDate'), type: TYPE.DATE},
  170. {name: '编制日期', value: getValueByKey(source.basicInformation, 'establishDate'), type: TYPE.DATE},
  171. {name: '审核日期', value: getValueByKey(source.basicInformation, 'auditDate'), type: TYPE.DATE},
  172. {name: '材料价格期', value: getValueByKey(source.basicInformation, 'materialPricePeriod')},
  173. {name: '合同价类型', value: getValueByKey(source.basicInformation, 'contractPriceType')},
  174. ];
  175. element.call(this, '项目信息', attrs);
  176. }
  177. //招标信息定义
  178. function BiddingInfo(source) {
  179. let attrs = [
  180. {name: '招标代理机构', value: getValueByKey(source.basicInformation, 'tenderingAgency')},
  181. {name: '造价工程师', value: getValueByKey(source.basicInformation, 'tenderCostEngineer')},
  182. {name: '造价工程师注册证号', value: getValueByKey(source.basicInformation, 'tenderCostEngineerNo')},
  183. {name: '招标工期', value: getValueByKey(source.basicInformation, 'tenderPeriod'), type: TYPE.INT},
  184. {name: '控制总价', value: source.summaryInfo.engineeringCost, type: TYPE.NUM2},
  185. ];
  186. element.call(this, '招标信息', attrs);
  187. }
  188. //投标信息定义
  189. function BidInfo(source) {
  190. let attrs = [
  191. {name: '投标人', value: getValueByKey(source.basicInformation, 'bidder')},
  192. {name: '造价工程师', value: getValueByKey(source.basicInformation, 'bidCostEngineer')},
  193. {name: '造价工程师注册证号', value: getValueByKey(source.basicInformation, 'bidCostEngineerNo')},
  194. {name: '项目经理', value: getValueByKey(source.basicInformation, 'projectManager')},
  195. {name: '投标工期', value: getValueByKey(source.basicInformation, 'biddingPeriod')},
  196. {name: '投标保证金', value: getValueByKey(source.basicInformation, 'biddingMargin'), type: TYPE.NUM2},
  197. {name: '质量承诺', value: getValueByKey(source.basicInformation, 'qualityCommitment')},
  198. {name: '担保类型', value: getValueByKey(source.basicInformation, 'guaranteeType')},
  199. {name: '投标总价', value: source.summaryInfo.engineeringCost, type: TYPE.NUM2},
  200. ];
  201. element.call(this, '投标信息', attrs);
  202. }
  203. //编制说明定义
  204. function CompilationIllustration(source) {
  205. let attrs = [
  206. {name: '内容', value: source.compilationIllustration},
  207. ];
  208. element.call(this, '编制说明', attrs);
  209. }
  210. //系统信息定义
  211. function SystemInfo(source) {
  212. let attrs = [
  213. {name: 'ID1', value: source.softInfo},
  214. {name: 'ID2', value: ''},
  215. {name: '生成时间', value: source.generatedTime, type: TYPE.DATE_TIME},
  216. ];
  217. element.call(this, '系统信息', attrs);
  218. }
  219. //费用构成定义
  220. function FeeFrom(summaryInfo) {
  221. let attrs = [
  222. {name: '工程费合计', value: summaryInfo.engineeringCost, type: TYPE.NUM2},
  223. {name: '分部分项清单合计', value: summaryInfo.subEngineering, type: TYPE.NUM2},
  224. {name: '措施项目清单合计', value: summaryInfo.measure, type: TYPE.NUM2},
  225. {name: '安全文明施工专项费', value: summaryInfo.safetyConstruction, type: TYPE.NUM2},
  226. {name: '其他项目清单合计', value: summaryInfo.other, type: TYPE.NUM2},
  227. {name: '规费', value: summaryInfo.charge, type: TYPE.NUM2},
  228. {name: '税金', value: summaryInfo.tax, type: TYPE.NUM2},
  229. ];
  230. element.call(this, '费用构成', attrs);
  231. }
  232. //单项工程定义
  233. function engineering(source) {
  234. let attrs = [
  235. {name: '编号', value: source.code, minLen: 1, maxLen: 255},
  236. {name: '名称', value: source.name, minLen: 1, maxLen: 255},
  237. {name: '金额', value: source.summaryInfo.engineeringCost, type: TYPE.NUM2},
  238. ];
  239. element.call(this, '单项工程', attrs);
  240. }
  241. //单位工程定义
  242. function tender(source) {
  243. const TAX = {
  244. 1: '一般计税',
  245. 2: '简易计税'
  246. };
  247. let attrs = [
  248. {name: '编号', value: source.code, minLen: 1, maxLen: 255},
  249. {name: '名称', value: source.name, minLen: 1, maxLen: 255},
  250. {name: '专业', value: source.property.engineering},
  251. {name: '金额', value: source.summaryInfo.engineeringCost, type: TYPE.NUM2},
  252. {name: '定额库编码', value: source.property.defaultRationLibCode},
  253. {name: '计税方法', value: TAX[source.property.taxType]},
  254. ];
  255. }
  256. //工程特征定义
  257. function engFeature(source) {
  258. let attrs = [
  259. {name: '建筑分类', value: source.feature.buildingClass, },
  260. {name: '工程分类', value: source.feature.projClass, },
  261. {name: '建设规模', value: 'todo', },
  262. {name: '工程类别', value: source.basicInformation.projectCategory} //取建设项目的工程类别
  263. ];
  264. element.call(this, '工程特征', attrs);
  265. }
  266. //特征项定义
  267. function featureItem(feature) {
  268. let attrs = [
  269. {name: '编码', value: ''},
  270. {name: '名称', value: feature.dispName},
  271. {name: '内容', value: feature.value},
  272. ];
  273. element.call(this, '特征项', attrs);
  274. }
  275. //单位工程费汇总定义
  276. function tenderFeeSummary() {
  277. element.call(this, '单位工程费汇总', []);
  278. }
  279. //计价程序费用行定义
  280. function dxfyRow(source) {
  281. let attrs = [
  282. {name: '序号', value: source.code},
  283. {name: '行代号', value: source.rowCode},
  284. {name: '项目名称', value: source.name},
  285. {name: '计算基础表达式', value: source.calcBase},
  286. {name: '计算基础说明', value: source.calcBaseAnnotation},
  287. {name: '费率', value: source.feeRate},
  288. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  289. {name: '其中暂估价', value: getFee(source.fees, 'estimate.totalFee'), type: TYPE.NUM2},
  290. {name: '费用类别', value: source.feeType, type: TYPE.INT},
  291. {name: '备注', value: source.remark},
  292. ];
  293. element.call(this, '计价程序费用行', attrs);
  294. }
  295. //分部分项清单
  296. function fbfxBills() {
  297. element.call(this, '分部分项清单', []);
  298. }
  299. //清单分部定义
  300. function fbBills(source) {
  301. let attrs = [
  302. {name: '编号', value: source.code, maxLen: 20},
  303. {name: '名称', value: source.name, minLen: 1, maxLen: 255},
  304. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  305. {name: '其中暂估价', value: getFee(source.fees, 'estimate.totalFee')},
  306. {name: '备注', value: source.remark}
  307. ];
  308. element.call(this, '清单分部', attrs);
  309. }
  310. //清单项目定义
  311. function fxbills(source) {
  312. let attrs = [
  313. {name: '项目编码', value: source.code, minLen: 1, maxLen: 20},
  314. {name: '项目名称', value: source.name, minLen: 1, maxLen: 500},
  315. {name: '单位', value: source.unit, minLen: 1, maxLen: 20},
  316. {name: '工程量', value: source.quantity, type: TYPE.DECIMAL},
  317. {name: '综合单价', value: getFee(source.fees, 'common.unitFee'), type: TYPE.DECIMAL},
  318. {name: '综合合价', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  319. {name: '其中暂估价', value: getFee(source.fees, 'estimate.totalFee'), type: TYPE.NUM2},
  320. {name: '主要清单标志', value: source.mainBills, type: TYPE.BOOL},
  321. {name: '暂估清单标志', value: source.isEstimate, type: TYPE.BOOL},
  322. {name: '备注', value: source.remark},
  323. ];
  324. element.call(this, '清单项目', attrs);
  325. }
  326. //项目特征定义
  327. function itemCharacter() {
  328. element.call(this, '项目特征', []);
  329. }
  330. //特征定义
  331. function feature(source) {
  332. let attrs = [
  333. {name: '特征名称', value: source.name},
  334. {name: '特征描述', value: source.value},
  335. ];
  336. element.call(this, '特征', attrs);
  337. }
  338. //工程内容定义
  339. function jobContent() {
  340. element.call(this, '工程内容', []);
  341. }
  342. //内容定义
  343. function content(content) {
  344. let attrs = [
  345. {name: '内容', value: content}
  346. ];
  347. element.call(this, '内容', attrs);
  348. }
  349. //组价内容定义
  350. function priceContent() {
  351. element.call(this, '组价内容', []);
  352. }
  353. //定额子目定义
  354. function ration(source) {
  355. let attrs = [
  356. {name: '定额编号', value: source.viewCode, minLen: 1, maxLen: 80},
  357. {name: '项目名称', value: source.viewCode, minLen: 1, maxLen: 255},
  358. {name: '单位', value: source.unit, minLen: 1, maxLen: 20},
  359. {name: '定额库编码', value: source.libCode},
  360. {name: '原始定额编号', value: source.code, minLen: 1, maxLen: 80},
  361. {name: '子目类型', value: source.code, type: TYPE.INT, enumeration: [0, 1, 2, 3, 4, 5, 6]},
  362. {name: '工程量', value: source.quantity, type: TYPE.DECIMAL},
  363. {name: '工程量计算式', value: source.quantityEXP},
  364. {name: '定额单价', value: getFee(source.fees, 'rationUnitPrice.unitFee'), type: TYPE.DECIMAL},
  365. {name: '定额合价', value: getFee(source.fees, 'rationUnitPrice.totalFee'), type: TYPE.NUM2},
  366. {name: '综合单价', value: getFee(source.fees, 'common.unitFee'), type: TYPE.DECIMAL},
  367. {name: '综合合价', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  368. {name: '单价构成文件ID', value: 0, type: TYPE.INT}, //todo
  369. {name: '分包标志', value: source.isSubcontract, type: TYPE.BOOL},
  370. {name: '备注', value: source.remark}
  371. ];
  372. element.call(this, '定额子目', attrs);
  373. }
  374. //工料分析定义
  375. function gljAnalyze() {
  376. element.call(this, '工料分析', []);
  377. }
  378. //人材机含量定义
  379. function gljContent(source) {
  380. let attrs = [
  381. {name: '人材机代码', value: source.code, minLen: 1, maxLen: 20},
  382. {name: '消耗量', value: source.quantity, type: TYPE.DECIMAL},
  383. {name: '总消耗量', value: source.totalQuantity, type: TYPE.DECIMAL},
  384. {name: '数量计算方式', value: 1, type: TYPE.INT},
  385. ];
  386. element.call(this, '人材机含量', attrs);
  387. }
  388. //费用组成
  389. function feeContent(source) {
  390. let attrs = [
  391. {name: '基价人工费单价', value: getFee(source.fees, 'labour.unitFee'), type: TYPE.DECIMAL},
  392. {name: '基价人工费合价', value: getFee(source.fees, 'labour.totalFee'), type: TYPE.NUM2},
  393. {name: '定额人工基价调整单价', value: 0, type: TYPE.DECIMAL}, //调整价目前只有08有,默认设置成0
  394. {name: '定额人工基价调整合价', value: 0, type: TYPE.NUM2},
  395. {name: '基价材料费单价', value: getFee(source.fees, 'material.unitFee'), type: TYPE.DECIMAL},
  396. {name: '基价材料费合价', value: getFee(source.fees, 'material.totalFee'), type: TYPE.NUM2},
  397. {name: '基价机械费单价', value: getFee(source.fees, 'machine.unitFee'), type: TYPE.DECIMAL},
  398. {name: '基价机械费合价', value: getFee(source.fees, 'machine.totalFee'), type: TYPE.NUM2},
  399. {name: '定额机上人工基价调整单价', value: 0, type: TYPE.DECIMAL},
  400. {name: '定额机上人工基价调整合价', value: 0, type: TYPE.NUM2},
  401. {name: '未计材料单价', value: getFee(source.fees, 'unratedMaterial.unitFee'), type: TYPE.DECIMAL},
  402. {name: '未计材料合价', value: getFee(source.fees, 'unratedMaterial.totalFee'), type: TYPE.NUM2},
  403. {name: '人材机价差单价', value: getFee(source.fees, 'gljDiff.unitFee'), type: TYPE.DECIMAL}, //人材机价差通过人工、材料、机械价差相加得出
  404. {name: '人材机价差合价', value: getFee(source.fees, 'gljDiff.totalFee'), type: TYPE.NUM2},
  405. {name: '暂估材料单价', value: getFee(source.fees, 'estimate.unitFee'), type: TYPE.DECIMAL},
  406. {name: '暂估材料合价', value: getFee(source.fees, 'estimate.totalFee'), type: TYPE.NUM2},
  407. {name: '管理费单价', value: getFee(source.fees, 'manage.unitFee'), type: TYPE.DECIMAL},
  408. {name: '管理费合价', value: getFee(source.fees, 'manage.totalFee'), type: TYPE.NUM2},
  409. {name: '利润单价', value: getFee(source.fees, 'profit.unitFee'), type: TYPE.DECIMAL},
  410. {name: '利润合价', value: getFee(source.fees, 'profit.totalFee'), type: TYPE.NUM2},
  411. {name: '风险单价', value: getFee(source.fees, 'risk.unitFee'), type: TYPE.DECIMAL}, //重庆08叫风险费 重庆18叫一般风险费
  412. {name: '风险合价', value: getFee(source.fees, 'risk.totalFee'), type: TYPE.NUM2},
  413. {name: '一般风险单价', value: getFee(source.fees, 'risk.unitFee'), type: TYPE.DECIMAL},
  414. {name: '一般风险合价', value: getFee(source.fees, 'risk.totalFee'), type: TYPE.NUM2},
  415. {name: '其他风险单价', value: getFee(source.fees, 'otherRisk.unitFee'), type: TYPE.DECIMAL},
  416. {name: '其他风险合价', value: getFee(source.fees, 'otherRisk.totalFee'), type: TYPE.NUM2},
  417. ];
  418. element.call(this, '费用组成', attrs);
  419. }
  420. //措施项目清单定义
  421. function csxmBills(source) {
  422. let attrs = [
  423. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  424. {name: '其中暂估价', value: getFee(source.fees, 'estimate.totalFee'), type: TYPE.NUM2},
  425. ];
  426. element.call(this, '措施项目清单', attrs);
  427. }
  428. //组织措施清单定义
  429. function zzcsBills(source) {
  430. let attrs = [
  431. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  432. ];
  433. element.call(this, '组织措施清单', attrs);
  434. }
  435. //组织措施分类定义
  436. function zzcsClass(source) {
  437. let attrs = [
  438. {name: '编码', value: source.code, maxLen: 20},
  439. {name: '名称', value: source.name, minLen: 1, maxLen: 255},
  440. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  441. {name: '备注', value: source.remark}
  442. ];
  443. element.call(this, '组织措施分类', attrs);
  444. }
  445. //公式计算措施项
  446. function formulaCalcMeasure(source) {
  447. let attrs = [
  448. {name: '序号', value: source.code, minLen: 1, maxLen:20},
  449. {name: '名称', value: source.name, minLen: 1, maxLen: 255},
  450. {name: '计算基础表达式', value: source.calcBase},
  451. {name: '计算基础说明', value: source.calcBaseAnnotation},
  452. {name: '费率', value: source.feeRate},
  453. {name: '金额', value: getFee(source.fees, 'common.totalFee')},
  454. {name: '金额', value: getFee(source.fees, 'common.totalFee')},
  455. {name: '暂估价标志', value: getFee(source.fees, 'common.totalFee')},
  456. {name: '备注', value: source.remark},
  457. {name: '费用类别', value: source.feeType, enumeration: [120201, 1204, 10041, 1206]},
  458. ]
  459. }
  460. //技术措施清单定义
  461. function jscsBills(source) {
  462. let attrs = [
  463. {name: '技术措施清单', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  464. {name: '其中暂估价', value: getFee(source.fees, 'estimate.totalFee'), type: TYPE.NUM2},
  465. ];
  466. element.call(this, '技术措施清单', attrs);
  467. }
  468. //技术措施分类
  469. function jscsClass(source) {
  470. let attrs = [
  471. {name: '编号', value: source.code},
  472. {name: '名称', value: source.name},
  473. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  474. {name: '其中暂估价', value: getFee(source.fees, 'estimate.totalFee'), type: TYPE.DECIMAL},
  475. ];
  476. element.call(this, '技术措施分类', attrs);
  477. }
  478. //其他项目清单定义
  479. function otherBills() {
  480. element.call(this, '其他项目清单', []);
  481. }
  482. //暂列金额定义
  483. function provisional(source) {
  484. let attrs = [
  485. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2}
  486. ];
  487. element.call(this, '暂列金额', attrs);
  488. }
  489. //暂列金额明细定义
  490. function provisionalDetail(source) {
  491. let attrs = [
  492. {name: '编号', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  493. {name: '项目名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  494. {name: '计量单位', value: source.unit, maxLen: 20},
  495. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  496. {name: '备注', value: source.remark}
  497. ];
  498. element.call(this, '暂列金额明细', attrs);
  499. }
  500. //专业工程暂估价定义
  501. function engineeringEstimate(source) {
  502. let attrs = [
  503. {name: '金额', value: getFee(source.fees, 'common.totalFee')}
  504. ];
  505. element.call(this, '专业工程暂估价', attrs);
  506. }
  507. //专业工程暂估明细定义
  508. function engineeringEstimateDetail(source) {
  509. let attrs = [
  510. {name: '编号', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  511. {name: '工程名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  512. {name: '工程内容', value: 'todo', maxLen: 2000}, //todo
  513. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  514. {name: '备注', value: source.remark}
  515. ];
  516. element.call(this, '专业工程暂估明细', attrs);
  517. }
  518. //计日工定义
  519. function dayWork(source) {
  520. let attrs = [
  521. {name: '金额', value: getFee(source.fees, 'common.totalFee')}
  522. ];
  523. element.call(this, '', attrs);
  524. }
  525. //人工定义
  526. function labour() {
  527. element.call(this, '人工', []);
  528. }
  529. //计日工项目定义
  530. function dayWorkItem(source) {
  531. let attrs = [
  532. {name: '编号', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  533. {name: '名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  534. {name: '单位', value: source.unit, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  535. {name: '数量', value: source.quantity, type: TYPE.DECIMAL},
  536. {name: '综合单价', value: source.quantity, type: TYPE.DECIMAL},
  537. {name: '综合合价', value: source.quantity, type: TYPE.NUM2},
  538. {name: '备注', value: source.remark}
  539. ];
  540. element.call(this, '计日工项目', attrs);
  541. }
  542. //材料定义
  543. function material() {
  544. element.call(this, '材料', []);
  545. }
  546. //施工机械定义
  547. function machine() {
  548. element.call(this, '施工机械', []);
  549. }
  550. //总承包服务费定义
  551. function turnKeyContract(source) {
  552. let attrs = [
  553. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2}
  554. ];
  555. element.call(this, '总承包服务费', attrs);
  556. }
  557. //总承包服务费分类定义
  558. function turnKeyContractClass(source) {
  559. let attrs = [
  560. {name:'编号', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  561. {name:'名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  562. {name:'备注', value: source.remark}
  563. ];
  564. element.call(this, '总承包服务费分类', attrs);
  565. }
  566. //总承包服务费费用项定义
  567. function turnKeyContractItem(source) {
  568. let attrs = [
  569. {name: '编号', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  570. {name: '工程名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  571. {name: '计算基础', value: 0, type: TYPE.DECIMAL}, //todo
  572. {name: '服务内容', value: '', maxLen: 255}, //todo
  573. {name: '费率', value: source.feeRate, type: TYPE.DECIMAL},
  574. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  575. {name: '备注', value: source.remark}
  576. ];
  577. element.call(this, '总承包服务费费用项', attrs);
  578. }
  579. //其他定义
  580. function other(source) {
  581. let attrs = [
  582. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2}
  583. ];
  584. element.call(this, '其他', attrs);
  585. }
  586. //其他列项定义
  587. function otherItem(source) {
  588. let attrs = [
  589. {name: '序号', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  590. {name: '名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  591. {name: '计算基础', value: source.calcBase, maxLen: 255},
  592. {name: '费率', value: source.feeRate, type: TYPE.DECIMAL},
  593. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  594. {name: '不计入合价标志', value: source.isEstimate, type: TYPE.BOOL},
  595. {name: '备注', value: source.remark, maxLen: 255}
  596. ];
  597. element.call(this, '其他列项', attrs);
  598. }
  599. //规费和税金清单定义
  600. function chargeTaxBills() {
  601. element.call(this, '规费和税金清单', []);
  602. }
  603. //费用项定义
  604. function feeItem(source) {
  605. let attrs = [
  606. {name: '序号', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  607. {name: '行代号', value: source.rowCode, maxLen: 20},
  608. {name: '名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  609. {name: '计算基础表达式', value: source.calcBase, maxLen: 255},
  610. {name: '计算基础说明', value: source.calcBaseAnnotation, maxLen: 255},
  611. {name: '费率', value: source.feeRate, type: TYPE.DECIMAL},
  612. {name: '金额', value: getFee(source.fees, 'common.totalFee'), type: TYPE.NUM2},
  613. {name: '费用类别', value: source.feeType, enumeration: [800, 900, 9001, 9002, 9003]},
  614. {name: '备注', value: source.remark, maxLen: 255}
  615. ]
  616. }
  617. //人材机汇总定义
  618. function gljSummary() {
  619. element.call(this, '人材机汇总', []);
  620. }
  621. //人材机定义
  622. function glj(source) {
  623. let attrs = [
  624. {name: '代码', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  625. {name: '名称', value: source.name, minLen: 1, maxLen: 255, whiteSpace: WHITE_SPACE.COLLAPSE},
  626. {name: '规格', value: source.spec, maxLen: 255},
  627. {name: '单位', value: source.unit, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  628. {name: '原始代码', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  629. {name: '费用类别', value: source.feeType, enumeration: [1, 2, 3, 4]},
  630. {name: '配比类别', value: '', type: TYPE.INT}, //todo
  631. {name: '主要材料类别', value: '', type: TYPE.INT}, //todo
  632. {name: '主要材料单位系数', value: '', type: TYPE.DECIMAL}, //todo
  633. {name: '材料耗用类型', value: '', type: TYPE.INT}, //todo
  634. {name: '供货方式', value: '', type: TYPE.INT}, //todo
  635. {name: '暂估材料标志', value: !!source.is_evaluate, type: TYPE.BOOL},
  636. {name: '不计税设备标志', value: !!source.is_adjust_price, type: TYPE.BOOL}, //todo
  637. {name: '单价不从明细汇总标志', value: !!source.excludeRatio, type: TYPE.BOOL}, //todo
  638. {name: '定额价', value: source.basePrice, type: TYPE.DECIMAL},
  639. {name: '定额价调整', value: '', type: TYPE.DECIMAL}, //todo
  640. {name: '市场价', value: source.marketPrice, type: TYPE.DECIMAL},
  641. {name: '数量', value: source.quantity, type: TYPE.DECIMAL},
  642. {name: '产地', value: source.originPlace, maxLen: 255},
  643. {name: '厂家', value: source.vender, maxLen: 255},
  644. {name: '质量等级', value: source.qualityGrace, maxLen: 255},
  645. {name: '品牌', value: source.brand, maxLen: 255},
  646. {name: '备注', value: source.quantity, maxLen: 255},
  647. ];
  648. element.call(this, '人材机', attrs);
  649. }
  650. //人材机配比定义
  651. function gljRatio(source) {
  652. let attrs = [
  653. {name: '明细材料代码', value: source.code, minLen: 1, maxLen: 20, whiteSpace: WHITE_SPACE.COLLAPSE},
  654. {name: '数量', value: source.quantity, type: TYPE.DECIMAL}
  655. ];
  656. element.call(this, '人材机配比', attrs);
  657. }
  658. return function (granularity) {
  659. this.GRANULARITY = {
  660. PROJECT: 1, //导出建设项目
  661. ENGINEERING: 2, //导出单项工程
  662. TENDER: 3 //导出单位工程
  663. };
  664. //默认导出建设项目
  665. if (!granularity || ![1, 2, 3].includes(granularity)) {
  666. granularity = this.GRANULARITY.PROJECT;
  667. }
  668. this.failList = failList;
  669. this.granularity = granularity;
  670. //目前的数据
  671. let curData = null;
  672. //唯一性约束
  673. let contraints = {};
  674. async function loadProject(tenderID) {
  675. //拉取标段数据:建设项目、单项工程、单位工程数据
  676. let projectData = await ajaxPost('/pm/api/getProjectByGranularity', {user_id: userID, tenderID: tenderID, granularity: granularity});
  677. if (!projectData) {
  678. throw '获取项目数据错误';
  679. }
  680. //标段
  681. let project = curData = new Project({basicInformation: projectData.property.basicInformation, name: projectData.name});
  682. //项目信息
  683. let projectInfo = new ProjectInfo({basicInformation: projectData.property.basicInformation});
  684. project.children.push(projectInfo);
  685. //招标信息
  686. let biddingInfo = new BiddingInfo({basicInformation: projectData.property.basicInformation, summaryInfo: projectData.summaryInfo[projectData.ID]});
  687. projectInfo.children.push(biddingInfo);
  688. //投标信息
  689. let bidInfo = new BidInfo({basicInformation: projectData.property.basicInformation, summaryInfo: projectData.summaryInfo[projectData.ID]});
  690. projectInfo.children.push(bidInfo);
  691. //编制说明
  692. let compilationIll = new CompilationIllustration({compilationIllustration: projectData.property.compilationIllustration});
  693. project.children.push(compilationIll);
  694. //系统信息
  695. let generatedTime = moment(Date.now()).format('YYYY-MM-DDTHH:mm:ss'),
  696. sysInfoSource = {softInfo: projectData.softInfo, generatedTime},
  697. sysInfo = new SystemInfo(sysInfoSource);
  698. project.children.push(sysInfo);
  699. //费用构成
  700. let feeForm = new FeeFrom(projectData.summaryInfo[projectData.ID]);
  701. project.children.push(feeForm);
  702. }
  703. /*
  704. * 加载数据
  705. * */
  706. this.loadData = async function(tenderID) {
  707. await loadProject(tenderID);
  708. return curData;
  709. };
  710. /*
  711. * 转换数据,将数据转换成可被导出成xml的结构
  712. * {element: '标段', attrs: [{name: '属性1', value: 't'}], children: [...]} to
  713. * {'标段': {...}, '_属性1': t}
  714. * */
  715. /*
  716. * 导出数据
  717. * */
  718. this.toXml = function () {
  719. }
  720. }
  721. })();