浏览代码

1. template_node单元测试
2. 指标模板,导入Excel文件,识别四则运算

MaiXinRong 7 年之前
父节点
当前提交
53e3a8db97

+ 1 - 1
app/controller/template_controller.js

@@ -24,7 +24,7 @@ module.exports = app => {
          */
         async index (ctx) {
             const id = ctx.queries.id ? ctx.queries.id[0] : 1;
-            const node = await ctx.service.templateNode.getAllDataByCondition({template_id: 1});
+            const node = await ctx.service.templateNode.getAllDataByCondition({ where: { template_id: 1 } });
             for (const n of node) {
                 n.url = '/template?id=' + n.node_id;
                 n.target = '_self';

+ 31 - 0
app/extend/helper.js

@@ -345,6 +345,37 @@ module.exports = {
         }
     },
 
+    splitByOperator(expr) {
+        const exprStack = [];
+        const result = [];
+        for(let i = 0, len = expr.length; i < len; i++){
+            const cur = expr[i];
+            if(cur !== ' ' ){
+                exprStack.push(cur);
+            }
+        }
+        let param = '', isParamBefore = false;
+        while(exprStack.length > 0){
+            const cur = exprStack.shift();
+            if (this.isOperator(cur)) {
+                if (isParamBefore) {
+                    result.push(param);
+                    param = '';
+                }
+                result.push(cur);
+                isParamBefore = false;
+            } else {
+                param = param + cur;
+                isParamBefore = true;
+                if (exprStack.length === 0) {
+                    result.push(param);
+                    param = '';
+                }
+            }
+        }
+        return result;
+    },
+
     calcExprStr(expr) {
         try {
             const result = mathjs.eval(expr);

+ 1 - 1
app/public/js/lib_detail.js

@@ -28,7 +28,7 @@ $(document).ready(function() {
             {title: '项目节编号', field: 'code', width: 120, cellType: 'tree', vAlign: 1, readOnly: true},
             {title: '清单编号', field: 'b_code', width: 80, vAlign: 1, readOnly: true},
             {title: '名称', field: 'name', width: 200, vAlign: 1, readOnly: true},
-            {title: '单位', field: 'units', width: 50, vAlign: 1, readOnly: true},
+            {title: '单位', field: 'units', width: 62, vAlign: 1, hAlign: 1, readOnly: true},
             {title: '数量1', field: 'dgn_quantity1', width: 60, type: 'Number', vAlign: 1, readOnly: true},
             {title: '数量2', field: 'dgn_quantity2', width: 60, type: 'Number', vAlign: 1, readOnly: true},
             {title: '金额', field: 'total_price', width: 60, type: 'Number', vAlign: 1, readOnly: true},

+ 1 - 1
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -191,7 +191,7 @@ const SpreadJsObj = {
                 sheet.zh_setting.cols.forEach(function (col, j) {
                     const cell = sheet.getCell(i, j);
                     if (col.field !== '' && data[col.field]) {
-                        cell.value(data[col.field]).locked(col.readOnly || false).vAlign(col.vAlign);
+                        cell.value(data[col.field]).locked(col.readOnly || false).vAlign(col.vAlign).hAlign(col.hAlign);
                     } else {
                         cell.locked(col.readOnly || false);
                     }

+ 2 - 2
app/service/template_index.js

@@ -28,9 +28,9 @@ module.exports = app => {
          * @param transaction - 事务
          * @returns {Promise<void>}
          */
-        async importData(data, transaction) {
+        async importData(data, transaction, templateId = 1) {
             const datas = data instanceof Array ? data : [data];
-            await transaction.delete(this.tableName, {template_id: 1});
+            await transaction.delete(this.tableName, {template_id: templateId});
             const insertResult = await transaction.insert(this.tableName, datas);
             if (insertResult.affectedRows !== datas.length) {
                 throw '导入指标错误';

+ 37 - 21
app/service/template_node.js

@@ -33,12 +33,14 @@ module.exports = app => {
          * @param {Array} params - 参数数组
          * @param {Array} defaultParams - 默认参数数组
          * @param {Number} nodeId - 指标节点Id
+         * @param {Number} tempalteId - 指标模板Id
          * @private
          */
-        _loadDefaultParam(params, defaultParams, nodeId) {
+        _loadDefaultParam(params, defaultParams, nodeId, templateId = 1) {
             const newParams = JSON.parse(JSON.stringify(defaultParams));
             for (const p of newParams) {
                 p.node_id = nodeId;
+                p.template_id = templateId;
                 params.push(p);
             }
         }
@@ -66,13 +68,16 @@ module.exports = app => {
          * @param {String} rule - 指标规则
          * @param {Number} nodeId - 指标节点id
          * @param {Array} params - 参数列表
+         * @param {Number} templateId - 解析至的模板Id
          * @returns {*[]}
          * @private
          */
-        _parseParam(rule, nodeId, params) {
+        _parseParam(rule, nodeId, params, templateId = 1) {
             if (rule === '') { return ['', '']; }
             const self = this;
-            const ruleParams = rule.split('/');
+            const ruleParams = this.ctx.helper.splitByOperator(rule);
+            const codeParams = [];
+            const parseParams = [];
             const nodeParams = this._filterNodeParams(params, nodeId);
             const addParam = function (paramName) {
                 if (paramName === '') { return ''; }
@@ -82,7 +87,7 @@ module.exports = app => {
                 }
                 if (!param) {
                     const newParam = {
-                        template_id: 1,
+                        template_id: templateId,
                         node_id: nodeId,
                         param_id: nodeParams.length + 1,
                         code: paramCode[nodeParams.length],
@@ -97,12 +102,17 @@ module.exports = app => {
                 }
             };
             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 + ')'];
+                for (const i in ruleParams) {
+                    if (!this.ctx.helper.isOperator(ruleParams[i])) {
+                        const paramCode = addParam(ruleParams[i]);
+                        codeParams.push(paramCode);
+                        parseParams.push(paramCode + '(' + ruleParams[i] + ')');
+                    } else {
+                        codeParams.push(ruleParams[i]);
+                        parseParams.push(ruleParams[i]);
+                    }
+                }
+                return [codeParams.join(''), parseParams.join('')];
             } else {
                 const paramCode = addParam(rule);
                 return [paramCode, paramCode + '(' + rule + ')'];
@@ -140,15 +150,16 @@ module.exports = app => {
          * @param {Object} excelSheet
          * @param {Array} nodes - 解析后的指标节点
          * @param {Array} indexes - 解析后的指标
+         * @param {Number} templateId - 解析至的模板Id
          * @private
          */
-        _parseSheetData(excelSheet, nodes, indexes, params) {
+        _parseSheetData(excelSheet, nodes, indexes, params, templateId = 1) {
             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,
+                            template_id: templateId,
                             node_id: nodes.length + 1,
                             node_pid: this._findParentId(row[0], nodes) || -1,
                             code: row[0],
@@ -165,6 +176,7 @@ module.exports = app => {
                         node_id: nodes.length,
                         index_id: indexes.length + 1,
                         rule: row[9] ? row[9] : '',
+                        template_id: templateId,
                     };
                     if (row[4] === '√') {
                         index.index_type = 1;
@@ -175,7 +187,7 @@ module.exports = app => {
                     } else if (row[7] === '√') {
                         index.index_type = 4;
                     }
-                    [index.calc_rule, index.parse_rule] = this._parseParam(index.rule, index.node_id, params);
+                    [index.calc_rule, index.parse_rule] = this._parseParam(index.rule, index.node_id, params, templateId);
                     indexes.push(index);
                 }
             }
@@ -187,25 +199,29 @@ module.exports = app => {
          * @param {Array} excelSheets - Excel文件中的全部工作表
          * @returns {Promise<boolean>}
          */
-        async importData(excelSheets) {
+        async importData(excelSheets, templateId = 1) {
             let result = false;
             const limit = 30000;
             const transaction = await this.db.beginTransaction();
             try {
                 const nodes = [], indexes = [], params = [];
-                this._loadDefaultParam(params, paramConst.defaultGlobalParams, 0);
+                this._loadDefaultParam(params, paramConst.defaultGlobalParams, 0, templateId);
                 for (const sheet of excelSheets) {
-                    this._parseSheetData(sheet, nodes, indexes, params);
+                    this._parseSheetData(sheet, nodes, indexes, params, templateId);
                 }
 
                 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) {
+                    // 删除旧数据
+                    await transaction.delete(this.tableName, {template_id: templateId});
+                    // 插入指标节点数据
+                    const nodeResult = await transaction.insert(this.tableName, nodes);
+                    if (nodeResult.affectedRows !== nodes.length) {
                         throw '导入指标节点错误';
                     }
-                    await this.ctx.service.templateIndex.importData(indexes, transaction);
-                    await this.ctx.service.templateParam.importData(params, transaction);
+                    // 插入指标数据
+                    await this.ctx.service.templateIndex.importData(indexes, transaction, templateId);
+                    // 插入指标参数
+                    await this.ctx.service.templateParam.importData(params, transaction, templateId);
                 } else {
                     throw 'Excel文件中无标准的指标数据';
                 }

+ 2 - 2
app/service/template_param.js

@@ -29,9 +29,9 @@ module.exports = app => {
          * @param transaction - 事务
          * @returns {Promise<void>}
          */
-        async importData(data, transaction) {
+        async importData(data, transaction, templateId = 1) {
             const datas = data instanceof Array ? data : [data];
-            await transaction.delete(this.tableName, {template_id: 1});
+            await transaction.delete(this.tableName, {template_id: templateId});
             const insertResult = await transaction.insert(this.tableName, datas);
             if (insertResult.affectedRows !== datas.length) {
                 throw '导入指标参数错误';

+ 1 - 1
app/view/template/index.ejs

@@ -31,7 +31,7 @@
     <div class="content-wrap">
         <div class="c-body">
             <div class="sjs-height-1">
-                <table class="table table-bordered">
+                <table class="table table-sm table-bordered">
                     <tr>
                         <th>指标编号</th>
                         <th>指标名称</th>

+ 50 - 3
test/app/service/template_node.test.js

@@ -11,17 +11,64 @@
 const { app, assert } = require('egg-mock/bootstrap');
 // excel解析
 const excel = require('node-xlsx');
+const paramConst = require('../../../app/const/template_param');
 
 describe('test/app/service/template_node.test.js', () => {
-    it('_parseSheetData test', function () {
+    it('_parseSheetData test xls File', function () {
         const ctx = app.mockContext();
         const fileName = app.baseDir + '/test/app/service/test.xls';
         const sheets = excel.parse(fileName);
-        const nodes = [], indexes = [];
+        const nodes = [], indexes = [], params = [];
+
         for (const sheet of sheets) {
-            ctx.service.templateNode._parseSheetData(sheet, nodes, indexes);
+            ctx.service.templateNode._parseSheetData(sheet, nodes, indexes, params);
         }
+
         assert(nodes.length === 5);
         assert(indexes.length === 42);
+        assert(params.length === 59);
+    });
+    it('_parseSheetData test xlsx File', function () {
+        const ctx = app.mockContext();
+        const fileName = app.baseDir + '/test/app/service/test.xlsx';
+        const sheets = excel.parse(fileName);
+        const nodes = [], indexes = [], params = [];
+
+        for (const sheet of sheets) {
+            ctx.service.templateNode._parseSheetData(sheet, nodes, indexes, params);
+        }
+
+        assert(nodes.length === 3);
+        assert(indexes.length === 12);
+        assert(params.length === 21);
+    });
+
+    it('importData test xls File', function* () {
+        const ctx = app.mockContext();
+        const fileName = app.baseDir + '/test/app/service/test.xls';
+        const sheets = excel.parse(fileName), templateId = 0;
+
+        yield ctx.service.templateNode.importData(sheets, templateId);
+
+        const nodes = yield ctx.service.templateNode.getAllDataByCondition({where: {template_id: templateId}});
+        assert(nodes.length === 5);
+        const indexes = yield ctx.service.templateIndex.getAllDataByCondition({where: {template_id: templateId}});
+        assert(indexes.length === 42);
+        const params = yield ctx.service.templateParam.getAllDataByCondition({where: {template_id: templateId}});
+        assert(params.length === 57);
+    });
+    it('importData test xlsx File', function* () {
+        const ctx = app.mockContext();
+        const fileName = app.baseDir + '/test/app/service/test.xlsx';
+        const sheets = excel.parse(fileName), templateId = 0;
+
+        yield ctx.service.templateNode.importData(sheets, templateId);
+
+        const nodes = yield ctx.service.templateNode.getAllDataByCondition({where: {template_id: templateId}});
+        assert(nodes.length === 3);
+        const indexes = yield ctx.service.templateIndex.getAllDataByCondition({where: {template_id: templateId}});
+        assert(indexes.length === 12);
+        const params = yield ctx.service.templateParam.getAllDataByCondition({where: {template_id: templateId}});
+        assert(params.length === 31);
     });
 });