template_node.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. 'use strict';
  2. /**
  3. * 指标节点业务类
  4. *
  5. * @author Mai
  6. * @date 2018/4/19
  7. * @version
  8. */
  9. const paramCode = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
  10. 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'aa', 'ab', 'ac', 'ad', 'ae', 'af',
  11. 'ag', 'ah', 'ai', 'aj', 'ak', 'al', 'am', 'an', 'ao', 'ap', 'aq', 'ar', 'as', 'at', 'au',
  12. 'av', 'aw', 'ax', 'ay', 'az'];
  13. const paramConst = require('../const/template_param');
  14. const nodeConst = require('../const/template_node');
  15. module.exports = app => {
  16. class TemplateNode extends app.BaseService {
  17. /**
  18. * 构造函数
  19. *
  20. * @param {Object} ctx - egg全局context
  21. * @return {void}
  22. */
  23. constructor(ctx) {
  24. super(ctx);
  25. this.tableName = 'template_node';
  26. }
  27. /**
  28. * 加载默认节点参数
  29. * @param {Array} params - 参数数组
  30. * @param {Array} defaultParams - 默认参数数组
  31. * @param {Number} nodeId - 指标节点Id
  32. * @private
  33. */
  34. _loadDefaultParam(params, defaultParams, nodeId) {
  35. const newParams = JSON.parse(JSON.stringify(defaultParams));
  36. for (const p of newParams) {
  37. p.node_id = nodeId;
  38. params.push(p);
  39. }
  40. }
  41. /**
  42. * 过滤指标节点的参数(含节点参数初始化)
  43. * @param {Array} params - 全部参数数组
  44. * @param {Number} nodeId - 指标节点Id
  45. * @private
  46. */
  47. _filterNodeParams(params, nodeId) {
  48. let nodeParams = params.filter(function (p) {
  49. return p.node_id === nodeId;
  50. });
  51. if (nodeParams.length > 0) {
  52. return nodeParams;
  53. } else {
  54. this._loadDefaultParam(params, paramConst.defaultNodeParams, nodeId);
  55. return params.filter(function (p) {
  56. return p.node_id === nodeId;
  57. });
  58. }
  59. }
  60. /**
  61. * 从计算规则中解析出指标参数
  62. * @param {String} rule - 指标规则
  63. * @param {Number} nodeId - 指标节点id
  64. * @param {Array} params - 参数列表
  65. * @returns {*[]}
  66. * @private
  67. */
  68. _parseParam(rule, nodeId, params) {
  69. if (rule === '') { return; }
  70. const self = this;
  71. const ruleParams = rule.split('/');
  72. const nodeParams = this._filterNodeParams(params, nodeId);
  73. const addParam = function (paramName) {
  74. if (paramName === '') { return ''; }
  75. let param = self.ctx.helper.findObj(paramConst.defaultGlobalParams, 'name', paramName);
  76. if (!param) {
  77. param = self.ctx.helper.findObj(nodeParams, 'name', paramName);
  78. }
  79. if (!param) {
  80. const newParam = {
  81. template_id: 1,
  82. node_id: nodeId,
  83. param_id: nodeParams.length + 1,
  84. code: paramCode[nodeParams.length],
  85. name: paramName,
  86. match_type: paramConst.matchType.non_match,
  87. };
  88. nodeParams.push(newParam);
  89. params.push(newParam);
  90. return newParam.code;
  91. } else {
  92. return param.code;
  93. }
  94. };
  95. if (ruleParams.length > 1) {
  96. const paramName1 = ruleParams[0];
  97. const paramCode1 = addParam(paramName1);
  98. const paramName2 = ruleParams.slice(1, ruleParams.length).join('/');
  99. const paramCode2 = addParam(paramName2);
  100. return [paramCode1 + '/' + paramCode2,
  101. paramCode1 + '(' + paramName1 + ')' + '/' + paramCode2 + '(' + paramName2 + ')'];
  102. } else {
  103. const paramCode = addParam(rule);
  104. return [paramCode, paramCode + '(' + rule + ')'];
  105. }
  106. }
  107. /**
  108. * 查找父节点(根据编号),忽略大小写
  109. * e.g. z1(z), z1-e(z1), z1-e-a(z1-e)
  110. * @param code
  111. * @param nodes
  112. * @returns {*}
  113. * @private
  114. */
  115. _findParentId(code, nodes) {
  116. if (nodes.length === 0) { return -1; }
  117. const codeList = code.split('-');
  118. if (codeList.length > 1) {
  119. codeList.splice(codeList.length - 1);
  120. const parentCode = codeList.join('-');
  121. for (const node of nodes) {
  122. if (parentCode.toLowerCase() === node.code.toLowerCase()) {
  123. return node.node_id;
  124. }
  125. }
  126. } else {
  127. for (const node of nodes) {
  128. if (code.toLowerCase().search(node.code.toLowerCase()) === 0) {
  129. return node.node_id;
  130. }
  131. }
  132. }
  133. }
  134. /**
  135. * 解析一个Excel工作表内的全部 指标节点 和 指标
  136. * @param {Object} excelSheet
  137. * @param {Array} nodes - 解析后的指标节点
  138. * @param {Array} indexes - 解析后的指标
  139. * @private
  140. */
  141. _parseSheetData(excelSheet, nodes, indexes, params) {
  142. for (const row of excelSheet.data) {
  143. if (!row[0]) { continue; }
  144. if (this.ctx.helper.ValidTemplateNodeCode(row[0])) {
  145. if (!this.ctx.helper.findObj(nodes, 'code', row[0])) {
  146. const node = {
  147. template_id: 1,
  148. node_id: nodes.length + 1,
  149. node_pid: this._findParentId(row[0], nodes) || -1,
  150. code: row[0],
  151. name: row[1],
  152. };
  153. nodes.push(node);
  154. }
  155. } else if (this.ctx.helper.ValidTemplateIndexCode(row[0])) {
  156. const index = {
  157. code: row[0],
  158. name: row[1],
  159. unit1: row[2],
  160. unit2: row[3],
  161. node_id: nodes.length,
  162. index_id: indexes.length + 1,
  163. rule: row[9]
  164. };
  165. if (row[4] === '√') {
  166. index.index_type = 1;
  167. } else if (row[5] === '√') {
  168. index.index_type = 2;
  169. } else if (row[6] === '√') {
  170. index.index_type = 3;
  171. } else if (row[7] === '√') {
  172. index.index_type = 4;
  173. }
  174. [index.calc_rule, index.parse_rule] = this._parseParam(index.rule, index.node_id, params);
  175. indexes.push(index);
  176. }
  177. }
  178. }
  179. /**
  180. * 导入Excel数据
  181. *
  182. * @param {Array} excelSheets - Excel文件中的全部工作表
  183. * @returns {Promise<boolean>}
  184. */
  185. async importData(excelSheets) {
  186. let result = false;
  187. const limit = 30000;
  188. const transaction = await this.db.beginTransaction();
  189. try {
  190. const nodes = [], indexes = [], params = [];
  191. this._loadDefaultParam(params, paramConst.defaultGlobalParams, 0);
  192. console.log(params);
  193. for (const sheet of excelSheets) {
  194. this._parseSheetData(sheet, nodes, indexes, params);
  195. }
  196. if (nodes.length > 0) {
  197. await transaction.delete(this.tableName, {template_id: 1});
  198. const insertResult = await transaction.insert(this.tableName, nodes);
  199. if (insertResult.affectedRows !== nodes.length) {
  200. throw '导入指标节点错误';
  201. }
  202. await this.ctx.service.templateIndex.importData(indexes, transaction);
  203. await this.ctx.service.templateParam.importData(params, transaction);
  204. } else {
  205. throw 'Excel文件中无标准的指标数据';
  206. }
  207. await transaction.commit();
  208. result = true;
  209. } catch(err) {
  210. await transaction.rollback();
  211. console.log(err);
  212. throw err;
  213. }
  214. return result;
  215. }
  216. /**
  217. * 保存指标节点绑定信息
  218. *
  219. * @param data
  220. * @returns {Promise<*>}
  221. */
  222. async updateNodeMatch(data, condition) {
  223. try {
  224. if (this.ctx.helper.validMatchCode(data.match_key)) {
  225. data.match_type = nodeConst.matchType.code;
  226. } else {
  227. data.match_type = nodeConst.matchType.name;
  228. }
  229. await this.db.update(this.tableName, data, {where: condition});
  230. } catch (err) {
  231. console.log(err);
  232. }
  233. return await this.getDataByCondition(condition);
  234. }
  235. }
  236. return TemplateNode;
  237. };