importStdInterfaceBase.js 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. 'use strict';
  2. const e = require("express");
  3. /**
  4. *
  5. *
  6. * @author Zhong
  7. * @date 2019/6/28
  8. * @version
  9. */
  10. const importXMLBase = (() => {
  11. //人材机调整法
  12. const AdjustType = {
  13. info: 'priceInfo', //造价信息差额调整法
  14. coe: 'priceCoe' //价格指数调整法
  15. };
  16. const CONFIG = Object.freeze({
  17. AdjustType
  18. });
  19. // xml字符实体
  20. const XMLEntity = {
  21. ' ': 'escape{space}',
  22. ' ': 'escape{simpleSpace}',
  23. '	': 'escape{tab}',
  24. '	': 'escape{simpleTab}',
  25. '
': 'escape{return}',
  26. '
': 'escape{simpleReturn}',
  27. '&#000A;': 'escape{newLine}',
  28. '
': 'escape{simpleNewLine}',
  29. '<': 'escape{less}',
  30. '>': 'escape{greater}',
  31. '&': 'escape{and}',
  32. '"': 'escape{quot}',
  33. ''': 'escape{apos}'
  34. };
  35. // 避免字符实体进行转义。原文本中含有xml字符实体,转换为其他字符。
  36. function escapeXMLEntity(str) {
  37. for (const [key, value] of Object.entries(XMLEntity)) {
  38. str = str.replace(new RegExp(key, 'g'), value);
  39. }
  40. return str;
  41. }
  42. // 将文本还原为字符实体
  43. function restoreXMLEntity(str) {
  44. for (const [key, value] of Object.entries(XMLEntity)) {
  45. str = str.replace(new RegExp(value, 'g'), key);
  46. }
  47. return str;
  48. }
  49. /*
  50. * 读取文件转换为utf-8编码的字符串
  51. * @param {Blob}file
  52. * @return {Promise}
  53. * */
  54. function readAsTextSync(file) {
  55. return new Promise((resolve, reject) => {
  56. const fr = new FileReader();
  57. fr.readAsText(file); // 默认utf-8,如果出现乱码,得看导入文件是什么编码
  58. fr.onload = function () {
  59. resolve(this.result);
  60. };
  61. fr.onerror = function () {
  62. reject('读取文件失败,请重试。');
  63. }
  64. });
  65. }
  66. /*
  67. * 根据字段数组获得所要字段的值 eg: 要获取标段下的单项工程: ['标段', '单项工程'];
  68. * @param {Object}source 源数据
  69. * {Array}fields 字段数组
  70. * @return {String}
  71. * @example getValue(source, ['标段', '_文件类型'])
  72. * */
  73. function getValue(source, fields) {
  74. let cur = source;
  75. for (const field of fields) {
  76. if (!cur[field]) {
  77. return '';
  78. }
  79. cur = cur[field];
  80. }
  81. return cur || '';
  82. }
  83. // 获取数据类型
  84. function _plainType(v) {
  85. return Object.prototype.toString.call(v).slice(8, -1);
  86. }
  87. /*
  88. * 获取某字段的值,强制返回数组
  89. * @param {Object}source 数据源
  90. * {Array}fields 取的字段
  91. * @return {Array}
  92. * @example arrayValue(source, ['标段', '单项工程'])
  93. * */
  94. function arrayValue(source, fields) {
  95. let target = getValue(source, fields);
  96. if (_plainType(target) === 'Object') {
  97. target = [target];
  98. } else if (_plainType(target) !== 'Array') {
  99. target = []
  100. }
  101. return target;
  102. }
  103. // 获取费用
  104. function getFee(fees, fields) {
  105. if (!Array.isArray(fees) || !fees.length) {
  106. return '0';
  107. }
  108. const feeData = fees.find(fee => fee.fieldName === fields[0]);
  109. return feeData[fields[1]] || '0';
  110. }
  111. // 合并价格
  112. function mergeFees(feesA, feesB) {
  113. feesB.forEach(feeB => {
  114. const sameKindFee = feesA.find(feeA => feeA.fieldName === feeB.fieldName);
  115. if (sameKindFee) {
  116. Object.assign(sameKindFee, feeB);
  117. } else {
  118. feesA.push(feeB);
  119. }
  120. });
  121. return feesA;
  122. }
  123. // 获取固定ID
  124. function getFlag(data) {
  125. return data.flags && data.flags[0] && data.flags[0].flag || 0;
  126. }
  127. // 获取布尔型的数据
  128. function getBool(v) {
  129. return v === 'true' ? true : false;
  130. }
  131. /*
  132. * 递归获取相关数据,eg:获取组织措施清单下的所有子清单,该子清单们可能由分类及公式措施项各种组合组成。(参考调用处)
  133. * @param {Object}src(数据源) {Array}fields(二维数组,数组里的成员由需要取的字段组成)
  134. * eg: ['组织措施分类'], ['公式计算措施项'],该层数据可能由组织措施分类 或 公式计算措施项组成 (同层不可同时存在)
  135. * {Function} 获得源数据后,需要提取的数据方法
  136. * @return {Array}
  137. * */
  138. function getItemsRecur(src, fields, extractFuc) {
  139. let itemsSrc = [];
  140. let curField = [''];
  141. for (const field of fields) {
  142. itemsSrc = arrayValue(src, field);
  143. if (itemsSrc.length) {
  144. curField = field;
  145. break;
  146. }
  147. }
  148. return itemsSrc.map(itemSrc => {
  149. const obj = extractFuc(itemSrc, curField);
  150. obj.items = getItemsRecur(itemSrc, fields, extractFuc);
  151. return obj;
  152. });
  153. }
  154. /*
  155. * 转换计算基数
  156. * 1.有子项数据,则清空基数
  157. * 2.行代号引用转换为ID引用
  158. * 3.对应字典代号转换,对应字典里找不到则设置成金额
  159. * @param {Array}billsData 清单数据
  160. * {Object}CalcBaseMap 基数映射
  161. * @return {void}
  162. * */
  163. function transformCalcBase(billsData, CalcBaseMap) {
  164. //行代号 - ID映射
  165. let rowCodeMap = {};
  166. billsData.forEach(data => {
  167. if (data.rowCode) {
  168. rowCodeMap[data.rowCode] = data.ID;
  169. }
  170. });
  171. for (let bills of billsData) {
  172. if (!bills.calcBase) {
  173. continue;
  174. }
  175. let sub = billsData.find(data => data.ParentID === bills.ID);
  176. //有子项数据,则清空基数,费率
  177. if (sub) {
  178. bills.calcBase = '';
  179. bills.feeRate = '';
  180. continue;
  181. }
  182. //提取基数
  183. bills.calcBase = bills.calcBase.replace(/\s/g, '');
  184. let bases = bills.calcBase.split(/[\+\-\*\/]/g);
  185. //提取操作符
  186. let oprs = bills.calcBase.match(/[\+\-\*\/]/g);
  187. //转换后的基数
  188. let newBase = [];
  189. let illegal = false; //不合法
  190. for (let base of bases) {
  191. if (rowCodeMap[base]) { //行引用
  192. newBase.push(`@${rowCodeMap[base]}`);
  193. } else if (CalcBaseMap[base]) { //基数字典
  194. newBase.push(CalcBaseMap[base]);
  195. } else { //都没匹配到,说明软件无法识别此基数
  196. illegal = true;
  197. break;
  198. }
  199. };
  200. if (illegal) {
  201. let fee = getFee(bills.fees, ['common', 'totalFee']);
  202. let feeRate = bills.feeRate && parseFloat(bills.feeRate) !== 0 ? parseFloat(bills.feeRate) : 0;
  203. if (fee && parseFloat(fee) !== 0 && feeRate) {
  204. bills.calcBase = scMathUtil.roundForObj(parseFloat(fee) * 100 / feeRate, 2);
  205. } else {
  206. bills.calcBase = fee !== '0' ? fee : '';
  207. }
  208. } else {
  209. let newCalcBase = '';
  210. for (let i = 0; i < newBase.length; i++) {
  211. newCalcBase += newBase[i];
  212. if (oprs && oprs[i]) {
  213. newCalcBase += oprs[i];
  214. }
  215. }
  216. bills.calcBase = newCalcBase;
  217. }
  218. }
  219. }
  220. // 获取必要的清单模板
  221. async function getNeedfulTemplate(templateLibID) {
  222. return await ajaxPost('/template/bills/api/getNeedfulTemplate',
  223. { templateLibID });
  224. }
  225. const UTIL = Object.freeze({
  226. escapeXMLEntity,
  227. restoreXMLEntity,
  228. getValue,
  229. arrayValue,
  230. getFee,
  231. mergeFees,
  232. getFlag,
  233. getBool,
  234. getItemsRecur,
  235. readAsTextSync,
  236. });
  237. // 获取接受上传的文件类型正则表达式
  238. function getAcceptReg(accepts) {
  239. const acceptsExp = accepts.reduce((acc, cur, index) => {
  240. return acc + `${index ? '|' : ''}\\${cur}`;
  241. }, '');
  242. return new RegExp(`(${acceptsExp})`, 'i');
  243. }
  244. return {
  245. CONFIG,
  246. UTIL,
  247. getAcceptReg,
  248. }
  249. })();