'use strict'; /** * 指标节点业务类 * * @author Mai * @date 2018/4/19 * @version */ const paramCode = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag', 'ah', 'ai', 'aj', 'ak', 'al', 'am', 'an', 'ao', 'ap', 'aq', 'ar', 'as', 'at', 'au', 'av', 'aw', 'ax', 'ay', 'az']; const defaultGlobalParams = [ { template_id: 1, node_id: 0, param_id: 1, code: 'g_a', name: '公路基本造价', },{ template_id: 1, node_id: 0, param_id: 2, code: 'g_b', name: '建安费', },{ template_id: 1, node_id: 0, param_id: 3, code: 'g_c', name: '工程建设其他费用', },{ template_id: 1, node_id: 0, param_id: 4, code: 'g_d', name: '路线总长度(主线长度)', },{ template_id: 1, node_id: 0, param_id: 5, code: 'g_e', name: '建筑总面积{路线总长度(主线长度)×路基(或桥隧)宽度}', },{ template_id: 1, node_id: 0, param_id: 6, code: 'g_f', name: '路基长度(指不含桥梁、隧道的路基长度(双幅平均计))', }, ]; module.exports = app => { class TemplateNode extends app.BaseService { /** * 构造函数 * * @param {Object} ctx - egg全局context * @return {void} */ constructor(ctx) { super(ctx); this.tableName = 'template_node'; } /** * 从计算规则中解析出指标参数 * @param {String} rule - 指标规则 * @param {Number} nodeId - 指标节点id * @param {Array} params - 参数列表 * @returns {*[]} * @private */ _parseParam(rule, nodeId, params) { if (rule === '') { return; } const self = this; const ruleParams = rule.split('/'); const nodeParams = params.filter(function (p) { return p.node_id === nodeId; }); const addParam = function (paramName) { if (paramName === '') { return ''; } let param = self.ctx.helper.findObj(defaultGlobalParams, 'name', paramName); if (!param) { param = self.ctx.helper.findObj(nodeParams, 'name', paramName); } if (!param) { const newParam = { template_id: 1, node_id: nodeId, param_id: nodeParams.length + 1, code: paramCode[nodeParams.length], name: paramName, }; nodeParams.push(newParam); params.push(newParam); return newParam.code; } else { return param.code; } } if (ruleParams.length > 1) { const paramName1 = ruleParams[0]; const paramCode1 = addParam(paramName1); const paramName2 = ruleParams.slice(1, ruleParams.length).join('/'); const paramCode2 = addParam(paramName2); return [paramCode1 + '/' + paramCode2, paramCode1 + '(' + paramName1 + ')' + '/' + paramCode2 + '(' + paramName2 + ')']; } else { const paramCode = addParam(rule); return [paramCode, paramCode + '(' + rule + ')']; } } /** * 查找父节点(根据编号),忽略大小写 * e.g. z1(z), z1-e(z1), z1-e-a(z1-e) * @param code * @param nodes * @returns {*} * @private */ _findParentId(code, nodes) { if (nodes.length === 0) { return -1; } const codeList = code.split('-'); if (codeList.length > 1) { codeList.splice(codeList.length - 1); const parentCode = codeList.join('-'); for (const node of nodes) { if (parentCode.toLowerCase() === node.code.toLowerCase()) { return node.node_id; } } } else { for (const node of nodes) { if (code.toLowerCase().search(node.code.toLowerCase()) === 0) { return node.node_id; } } } } /** * 解析一个Excel工作表内的全部 指标节点 和 指标 * @param {Object} excelSheet * @param {Array} nodes - 解析后的指标节点 * @param {Array} indexes - 解析后的指标 * @private */ _parseSheetData(excelSheet, nodes, indexes, params) { for (const row of excelSheet.data) { if (!row[0]) { continue; } if (this.ctx.helper.ValidTemplateNodeCode(row[0])) { if (!this.ctx.helper.findObj(nodes, 'code', row[0])) { const node = { template_id: 1, node_id: nodes.length + 1, node_pid: this._findParentId(row[0], nodes) || -1, code: row[0], name: row[1], }; nodes.push(node); } } else if (this.ctx.helper.ValidTemplateIndexCode(row[0])) { const index = { code: row[0], name: row[1], unit1: row[2], unit2: row[3], node_id: nodes.length, index_id: indexes.length + 1, rule: row[9] }; if (row[4] === '√') { index.index_type = 1; } else if (row[5] === '√') { index.index_type = 2; } else if (row[6] === '√') { index.index_type = 3; } else if (row[7] === '√') { index.index_type = 4; } [index.calc_rule, index.parse_rule] = this._parseParam(index.rule, index.node_id, params); indexes.push(index); } } } /** * 导入Excel数据 * * @param {Array} excelSheets - Excel文件中的全部工作表 * @returns {Promise} */ async importData(excelSheets) { let result = false; const limit = 30000; const transaction = await this.db.beginTransaction(); try { const nodes = [], indexes = [], params = []; for (const sheet of excelSheets) { this._parseSheetData(sheet, nodes, indexes, params); } if (nodes.length > 0) { await transaction.delete(this.tableName, {template_id: 1}); const insertResult = await transaction.insert(this.tableName, nodes); if (insertResult.affectedRows !== nodes.length) { throw '导入指标节点错误'; } await this.ctx.service.templateIndex.importData(indexes, transaction); await this.ctx.service.templateParam.importData(params.concat(defaultGlobalParams), transaction); } else { throw 'Excel文件中无标准的指标数据'; } await transaction.commit(); result = true; } catch(err) { await transaction.rollback(); throw err; } return result; } } return TemplateNode; };