Explorar el Código

Merge branch 'master' of http://192.168.1.41:3000/maixinrong/Calculation

TonyKang hace 5 años
padre
commit
bb821729c5

+ 47 - 1
app/base/base_bills_service.js

@@ -21,7 +21,6 @@ class BaseBillsSerivce extends TreeService {
 
     // 继承方法
     clearParentingData(data) {
-        console.log(1);
         data.unit_price = null;
         data.sgfh_qty = null;
         data.sgfh_tp = null;
@@ -449,6 +448,53 @@ class BaseBillsSerivce extends TreeService {
         const result = await this.db.queryOne(sql);
         return result;
     }
+
+    // 导入Excel
+    async importGclExcel(id, sheet, data) {
+        const node = await this.getDataById(id);
+        if (!node || !node.is_leaf || node.tender_id !== this.ctx.tender.id) throw '数据错误';
+
+        const maxId = await this._getMaxLid(this.ctx.tender.id);
+
+        const AnalysisExcel = require('../lib/analysis_excel').AnalysisGclExcelTree;
+        const analysisExcel = new AnalysisExcel(this.ctx);
+        const cacheData = analysisExcel.analysisData(sheet, node, maxId, data);
+
+        const datas = [];
+        for (const node of cacheData.items) {
+            datas.push({
+                id: node.id, tender_id: this.ctx.tender.id,
+                ledger_id: node.ledger_id,
+                ledger_pid: node.ledger_pid,
+                level: node.level,
+                order: node.order,
+                is_leaf: !node.children || node.children.length === 0,
+                full_path: node.full_path,
+                b_code: node.b_code,
+                name: node.name,
+                unit: node.unit,
+                sgfh_qty: node.sgfh_qty,
+                sgfh_tp: node.sgfh_tp,
+                quantity: node.quantity,
+                unit_price: node.unit_price,
+                total_price: node.total_price,
+                crid: node.crid,
+            });
+        }
+        const conn = await this.db.beginTransaction();
+        try {
+            await this.db.update(this.tableName, {id: node.id, is_leaf: false});
+            await this.db.insert(this.tableName, datas);
+            await conn.commit();
+        } catch(err) {
+            await conn.rollback();
+            throw err;
+        }
+        this._cacheMaxLid(this.ctx.tender.id, cacheData.keyNodeId);
+
+        node.is_leaf = false;
+        return { create: datas, update: [node]};
+    }
 }
 
 module.exports = BaseBillsSerivce;

+ 2 - 2
app/base/base_tree_service.js

@@ -579,7 +579,7 @@ class TreeService extends Service {
         const selects = await this.getDataByKidAndCount(mid, kid, count);
         const first = selects[0];
         const parent = await this.getDataByKid(mid, first[this.setting.pid]);
-        const childCount = parent ? this.count(this.getCondition({mid: mid, pid: parent[this.setting.id]})) : -1;
+        const childCount = parent ? await this.count(this.getCondition({mid: mid, pid: parent[this.setting.kid]})) : -1;
         let deleteData = [];
         for (const s of selects) {
             deleteData = deleteData.concat(await this.getDataByFullPath(mid, s[this.setting.fullPath] + '%'));
@@ -604,7 +604,7 @@ class TreeService extends Service {
 
             const updateData = await this.getNextsData(mid, first[this.setting.pid], first[this.setting.order] - 1);
             if (parent && childCount === count) {
-                const updateData1 = await this.getDataByKid(mid, parent[this.setting.id]);
+                const updateData1 = await this.getDataByKid(mid, parent[this.setting.kid]);
                 updateData.push(updateData1);
             }
             return { delete: deleteData, update: updateData };

+ 5 - 0
app/const/spread.js

@@ -45,6 +45,7 @@ const withCl = {
     pos: {
         cols: [
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 230, formatter: '@'},
+            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'},
             {title: '台账数量|设计量', colSpan: '4|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 100, type: 'Number'},
             {title: '|设计错漏增减', colSpan: '|1', rowSpan: '|1', field: 'sjcl_qty', hAlign: 2, width: 100, type: 'Number'},
             {title: '|其他错漏增减', colSpan: '|1', rowSpan: '|1', field: 'qtcl_qty', hAlign: 2, width: 100, type: 'Number'},
@@ -85,6 +86,7 @@ const withoutCl = {
     pos: {
         cols: [
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 230, formatter: '@'},
+            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'},
             {title: '设计量', colSpan: '1', rowSpan: '1', field: 'sgfh_qty', hAlign: 2, width: 120, type: 'Number'},
             {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
         ],
@@ -141,6 +143,7 @@ const stageTz = {
     pos: {
         cols: [
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@', readOnly: true},
+            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'},
             {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, formatter: '@', readOnly: true},
             {title: '本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},
@@ -203,6 +206,7 @@ const stageCl = {
     pos: {
         cols: [
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@'},
+            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'},
             {title: '台账数量|施工图复核', colSpan: '4|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|设计错漏增减', colSpan: '1', rowSpan: '|1', field: 'sjcl_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|其他错漏增减', colSpan: '1', rowSpan: '|1', field: 'qtcl_qty', hAlign: 2, width: 60, type: 'Number'},
@@ -268,6 +272,7 @@ const stageNoCl = {
     pos: {
         cols: [
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@'},
+            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'},
             {title: '设计量', colSpan: '1', rowSpan: '2', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},

+ 0 - 1
app/controller/deal_bills_controller.js

@@ -122,7 +122,6 @@ module.exports = app => {
                             data.push([db.code, db.name, db.unit, db.quantity, db.unit_price, db.total_price]);
                         }
                         const arraySheetData = this.ctx.helper.simpleXlsxSheetData(setting, data);
-                        console.log(arraySheetData);
                         xlsx.writeFile({
                             SheetNames: ['Sheet1'],
                             Sheets: {

+ 12 - 2
app/controller/ledger_controller.js

@@ -473,11 +473,21 @@ module.exports = app => {
          */
         async uploadExcel(ctx) {
             try {
+                const ueType = ctx.params.ueType;
                 const compressData = ctx.request.body.data;
                 const data = JSON.parse(LzString.decompressFromUTF16(compressData));
                 const responseData = { err: 0, msg: '', data: {}, };
-                const templateId = await this.ctx.service.valuation.getValuationTemplate(this.ctx.tender.data.valuation);
-                responseData.data = await ctx.service.ledger.importExcel(templateId, data);
+                switch (ueType) {
+                    case 'tz':
+                        const templateId = await this.ctx.service.valuation.getValuationTemplate(this.ctx.tender.data.valuation);
+                        responseData.data = await ctx.service.ledger.importExcel(templateId, data);
+                        break;
+                    case 'gcl2xmj':
+                        responseData.data = await ctx.service.ledger.importGclExcel(data.id, data.sheet);
+                        break;
+                    default:
+                        throw '数据错误';
+                }
                 ctx.body = responseData;
             } catch (err) {
                 this.log(err);

+ 1 - 1
app/controller/profile_controller.js

@@ -176,7 +176,7 @@ module.exports = app => {
                 response.msg = '绑定成功';
                 response.url = ctx.request.header.referer;
             } catch (error) {
-                console.log(error);
+                this.ctx.helper.log(error);
                 response.err = 1;
                 response.msg = error.toString();
             }

+ 40 - 8
app/controller/revise_controller.js

@@ -379,6 +379,18 @@ module.exports = app => {
             }
         }
 
+        async checkRevise(ctx) {
+            const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
+            if (revise.uid !== ctx.session.sessionUser.accountId) {
+                throw '修订数据错误';
+            } else if (revise.status === audit.revise.status.checking) {
+                throw '修订审批中,不可修改';
+            } else if (revise.status === audit.revise.status.checked) {
+                throw '修订已完成,如需修订台账,请新增修订';
+            }
+            return revise;
+        }
+
         async _billsBase(revise, type, data) {
             if (isNaN(data.id) || data.id <= 0) throw '数据错误';
             if (type !== 'add') {
@@ -498,18 +510,12 @@ module.exports = app => {
         async update(ctx) {
             try {
                 if (!ctx.tender.data) throw '标段数据错误';
-                const revise = await ctx.service.ledgerRevise.getLastestRevise(ctx.tender.id);
-                if (revise.uid !== ctx.session.sessionUser.accountId) {
-                    throw '修订数据错误';
-                } else if (revise.status === audit.revise.status.checking) {
-                    throw '修订审批中,不可修改';
-                } else if (revise.status === audit.revise.status.checked) {
-                    throw '修订已完成,如需修订台账,请新增修订';
-                }
                 const data = JSON.parse(ctx.request.body.data);
                 if (!data.postType || !data.postData) throw '数据错误';
                 const responseData = {err: 0, msg: '', data: {}};
 
+                const revise = await this.checkRevise(ctx);
+
                 switch (data.postType) {
                     case 'add':
                     case 'delete':
@@ -551,6 +557,32 @@ module.exports = app => {
         }
 
         /**
+         * 上传 清单Excel 并导入
+         * @param ctx
+         * @return {Promise<void>}
+         */
+        async uploadExcel(ctx) {
+            try {
+                const revise = await this.checkRevise(ctx);
+
+                const ueType = ctx.params.ueType;
+                const compressData = ctx.request.body.data;
+                const data = JSON.parse(LzString.decompressFromUTF16(compressData));
+                const responseData = { err: 0, msg: '', data: {}, };
+                switch (ueType) {
+                    case 'gcl2xmj':
+                        responseData.data = await ctx.service.reviseBills.importGclExcel(data.id, data.sheet, {crid: revise.id});
+                        break;
+                }
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+
+        }
+
+        /**
          * 新增审批人(Ajax)
          *
          * @param ctx

+ 4 - 4
app/controller/stage_controller.js

@@ -236,8 +236,8 @@ module.exports = app => {
             }
             //console.timeEnd('pre');
             //console.time('assign');
-            console.log('cur: ' + curStageData.length);
-            console.log('pre: ' + preStageData.length);
+            //console.log('cur: ' + curStageData.length);
+            //console.log('pre: ' + preStageData.length);
             this.ctx.helper.assignRelaData(posData, [
                 {data: curStageData, fields: ['contract_qty', 'qc_qty', 'postil'], prefix: '', relaId: 'pid'},
                 {data: preStageData, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}
@@ -308,8 +308,8 @@ module.exports = app => {
                 }
                 //console.timeEnd('pre');
                 //console.time('assign');
-                console.log('cur: ' + curStageData.length);
-                console.log('pre: ' + preStageData.length);
+                //console.log('cur: ' + curStageData.length);
+                //console.log('pre: ' + preStageData.length);
                 this.ctx.helper.assignRelaData(responseData.data, [
                     {data: curStageData, fields: ['contract_qty', 'qc_qty', 'postil'], prefix: '', relaId: 'pid'},
                     {data: preStageData, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}

+ 19 - 1
app/extend/helper.js

@@ -698,7 +698,12 @@ module.exports = {
      * @returns {*}
      */
     replaceReturn(str) {
-        return (str && typeof str === 'string') ? str.replace(/[\r\n]/g, '') : str;
+        // return str
+        //     ? (typeof str === 'string') ? str.replace(/[\r\n]/g, '') : str + ''
+        //     : str;
+        return (str && typeof str === 'string')
+            ? str.replace(/[\r\n]/g, '')
+            : !_.isNil(str) ? str + '' : str;
     },
 
     /**
@@ -845,5 +850,18 @@ module.exports = {
             {'!ref': outputPos[0] + ':' + outputPos[outputPos.length - 1]},
             {'!cols': setting.width.map((w) => Object.assign({}, {wpx: w}))});
         return result;
+    },
+
+    log(error) {
+        if (error.stack) {
+            this.ctx.logger.error(error);
+        } else {
+            this.ctx.getLogger('fail').info(JSON.stringify({
+                error: error,
+                project: this.ctx.session.sessionProject,
+                user: this.ctx.session.sessionUser,
+                body: this.ctx.session.body,
+            }));
+        }
     }
 };

+ 191 - 23
app/lib/analysis_excel.js

@@ -8,6 +8,25 @@
  * @version
  */
 const _ = require('lodash');
+const aeUtils = {
+    toNumber: function (value) {
+        let num = _.toNumber(value);
+        return _.isNaN(num) ? null : num;
+    },
+    checkColHeader: function (row, colHeaderMatch) {
+        const colsDef = {};
+        for (const iCol in row) {
+            const text = row[iCol];
+            for (const head in colHeaderMatch) {
+                const match = colHeaderMatch[head];
+                if (match.indexOf(text) >= 0) {
+                    colsDef[head] = iCol;
+                }
+            }
+        }
+        return colsDef;
+    }
+};
 
 class ImportBaseTree {
     /**
@@ -264,11 +283,6 @@ class AnalysisExcelTree {
         };
     }
 
-    toNumber (value) {
-        let num = _.toNumber(value);
-        return _.isNaN(num) ? null : num;
-    }
-
     /**
      * 读取项目节节点
      * @param {Array} row - excel行数据
@@ -281,10 +295,10 @@ class AnalysisExcelTree {
         node.name = this.ctx.helper.replaceReturn(row[this.colsDef.name]);
         node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]);
         const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, node.unit);
-        node.sgfh_qty = this.ctx.helper.round(this.toNumber(row[this.colsDef.sgfh_qty]), precision.value);
-        node.dgn_qty1 = this.toNumber(row[this.colsDef.dgn_qty1]);
-        node.dgn_qty2 = this.toNumber(row[this.colsDef.dgn_qty2]);
-        node.unit_price = this.toNumber(row[this.colsDef.unit_price]);
+        node.sgfh_qty = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.sgfh_qty]), precision.value);
+        node.dgn_qty1 = aeUtils.toNumber(row[this.colsDef.dgn_qty1]);
+        node.dgn_qty2 = aeUtils.toNumber(row[this.colsDef.dgn_qty2]);
+        node.unit_price = aeUtils.toNumber(row[this.colsDef.unit_price]);
         node.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]);
         node.memo = this.ctx.helper.replaceReturn(row[this.colsDef.memo]);
         // if (node.sgfh_qty && node.unit_price) {
@@ -319,8 +333,8 @@ class AnalysisExcelTree {
         node.name = this.ctx.helper.replaceReturn(row[this.colsDef.name]);
         node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]);
         const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, node.unit);
-        node.sgfh_qty = this.ctx.helper.round(this.toNumber(row[this.colsDef.sgfh_qty]), precision.value);
-        node.unit_price = this.toNumber(row[this.colsDef.unit_price]);
+        node.sgfh_qty = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.sgfh_qty]), precision.value);
+        node.unit_price = aeUtils.toNumber(row[this.colsDef.unit_price]);
         node.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]);
         node.memo = this.ctx.helper.replaceReturn(row[this.colsDef.memo]);
         // if (node.sgfh_qty && node.unit_price) {
@@ -352,7 +366,7 @@ class AnalysisExcelTree {
     _loadPos(row) {
         const pos = {};
         pos.name = this.ctx.helper.replaceReturn(row[this.colsDef.name]);
-        pos.sgfh_qty = this.toNumber(row[this.colsDef.sgfh_qty]);
+        pos.sgfh_qty = aeUtils.toNumber(row[this.colsDef.sgfh_qty]);
         pos.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]);
         return this.cacheTree.addPos(pos);
     }
@@ -391,16 +405,7 @@ class AnalysisExcelTree {
      * @param {Number} row - Excel数据行
      */
     checkColHeader(row) {
-        const colsDef = {};
-        for (const iCol in row) {
-            const text = row[iCol];
-            for (const head in this.colHeaderMatch) {
-                const match = this.colHeaderMatch[head];
-                if (match.indexOf(text) >= 0) {
-                    colsDef[head] = iCol;
-                }
-            }
-        }
+        const colsDef = aeUtils.checkColHeader(row, this.colHeaderMatch);
         if (colsDef.code && colsDef.b_code && colsDef.pos) {
             this.colsDef = colsDef;
         }
@@ -432,4 +437,167 @@ class AnalysisExcelTree {
     }
 }
 
-module.exports = AnalysisExcelTree;
+class ImportGclBaseTree {
+    /**
+     * 构造函数
+     * @param {Array} tempData - 清单模板数据
+     */
+    constructor (ctx, parent, maxId, defaultData) {
+        this.ctx = ctx;
+        this.parent = parent;
+        this.defaultData = defaultData;
+        // 常量
+        this.splitChar = '-';
+        // 索引
+        // 以code为索引
+        this.codeNodes = {};
+        this.items = [];
+
+        // 缓存
+        this.keyNodeId = maxId ? maxId + 1 : 1;
+        this.blankParent = null;
+    }
+
+    /**
+     * 根据 编号 查找 父项项目节
+     * @param {String} code - 子项编号
+     * @returns {*}
+     */
+    findParent(code) {
+        const codePath = code.split(this.splitChar);
+        if (codePath.length > 1) {
+            codePath.splice(codePath.length - 1, 1);
+            return this.codeNodes[codePath.join(this.splitChar)];
+        }
+    }
+
+    /**
+     * 添加 树节点 并完善该节点的树结构
+     * @param {Object} node - 添加节点
+     * @param {Object} parent - 父项
+     * @returns {*}
+     */
+    addNodeWithParent(node, parent) {
+        parent = parent ? parent : this.parent;
+        if (!parent.children) parent.children = [];
+
+        node.id = this.ctx.app.uuid.v4();
+        node.tender_id = this.ctx.tender.id;
+        node.ledger_id = this.keyNodeId;
+        this.keyNodeId += 1;
+        node.ledger_pid = parent.ledger_id;
+        node.level = parent.level + 1;
+        node.order = parent.children.length + 1;
+        node.full_path = parent.full_path + '-' + node.ledger_id;
+        parent.children.push(node);
+        node.children = [];
+        if (this.defaultData) _.assignIn(node, this.defaultData);
+        this.items.push(node);
+        if (!_.isNil(node.b_code) && node.b_code !== '') {
+            this.codeNodes[node.b_code] = node;
+        } else {
+            this.blankParent = node;
+        }
+        return node;
+    }
+
+    /**
+     * 添加 项目节
+     * @param {Object} node - 项目节
+     * @returns {*}
+     */
+    addNode(node) {
+        if (_.isNil(node.b_code) || node.b_code === '') {
+            return this.addNodeWithParent(node, null);
+        } else if (node.b_code.split(this.splitChar).length > 1) {
+            const parent = this.findParent(node.b_code);
+            return this.addNodeWithParent(node, parent ? parent : this.blankParent);
+        } else {
+            return this.addNodeWithParent(node, this.blankParent);
+        }
+    }
+}
+
+class AnalysisGclExcelTree {
+    /**
+     * 构造函数
+     */
+    constructor(ctx) {
+        this.ctx = ctx;
+        this.colsDef = null;
+        this.colHeaderMatch = {
+            b_code: ['编号', '清单编号', '子目号'],
+            name: ['名称'],
+            unit: ['单位'],
+            sgfh_qty: ['清单数量'], // 施工图复核数量
+            unit_price: ['单价'],
+        };
+    }
+
+    /**
+     * 读取表头并检查
+     * @param {Number} row - Excel数据行
+     */
+    checkColHeader(row) {
+        const colsDef = aeUtils.checkColHeader(row, this.colHeaderMatch);
+        if (colsDef.b_code) {
+            this.colsDef = colsDef;
+        }
+    }
+
+    loadRowData(row) {
+        const node = {};
+        node.b_code = this.ctx.helper.replaceReturn(row[this.colsDef.b_code]);
+        node.name = this.ctx.helper.replaceReturn(row[this.colsDef.name]);
+        if ((_.isNil(node.b_code) || node.b_code === '') && (_.isNil(node.name) || node.name === '')) return node;
+
+        node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]);
+        const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, node.unit);
+        node.sgfh_qty = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.sgfh_qty]), precision.value);
+        node.unit_price = aeUtils.toNumber(row[this.colsDef.unit_price]);
+        if (node.sgfh_qty && node.unit_price) {
+            node.sgfh_tp = this.ctx.helper.mul(node.sgfh_qty, node.unit_price, this.ctx.tender.info.decimal.tp);
+        } else {
+            node.sgfh_tp = null;
+        }
+        node.quantity = node.sgfh_qty;
+        node.total_price = node.sgfh_tp;
+        return this.cacheTree.addNode(node);
+    }
+
+    /**
+     * 将excel清单 平面数据 解析为 树结构数据
+     * @param {object} sheet - excel清单数据
+     * @param {Array} parentId - 导入至的节点id
+     * @returns {ImportBaseTree}
+     */
+    analysisData(sheet, parent, maxId, defaultData) {
+        try {
+            this.colsDef = null;
+            this.cacheTree = new ImportGclBaseTree(this.ctx, parent, maxId, defaultData);
+            this.errorData = [];
+            this.loadEnd = false;
+
+            for (const iRow in sheet.rows) {
+                const row = sheet.rows[iRow];
+                if (this.colsDef && !this.loadEnd) {
+                    const result = this.loadRowData(row);
+                    // 读取失败则写入错误数据 todo 返回前端告知用户?
+                    if (!result) {
+                        this.errorData.push({
+                            serialNo: iRow,
+                            data: row,
+                        });
+                    }
+                } else {
+                    this.checkColHeader(row);
+                }
+            }
+            return this.cacheTree;
+        } catch(err) {
+            this.ctx.helper.log(err);
+        }
+    }
+}
+
+module.exports = { AnalysisExcelTree, AnalysisGclExcelTree };

+ 1 - 1
app/lib/ledger.js

@@ -166,7 +166,7 @@ class billsTree {
      * @returns {boolean}
      */
     isLeafXmj(node) {
-        if (!node.code) {
+        if (node.b_code && node.b_code !== '') {
             return false;
         }
         for (const child of node.children) {

+ 8 - 0
app/lib/stage_im.js

@@ -11,6 +11,7 @@
 const Ledger = require('./ledger');
 const imType = require('../const/tender').imType;
 const mergeChar = ';';
+const version = '1.0';
 
 class StageIm {
     constructor (ctx) {
@@ -320,6 +321,8 @@ class StageIm {
                     im.gclBills.push(b);
                     this.ImBillsData.push(b);
                 }
+                b.quantity = this.ctx.helper.add(b.quantity, p.quantity);
+
                 b.jl = this.ctx.helper.add(b.jl, p.gather_qty);
                 b.contract_jl = this.ctx.helper.add(b.contract_jl, p.contract_qty);
                 b.qc_jl = this.ctx.helper.add(b.qc_jl, p.qc_qty);
@@ -490,6 +493,7 @@ class StageIm {
                 im = {
                     id: this.ImData.length + 1,
                     lid: node.id, pid: '', code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
+                    quantity: 0,
                     jl: 0, contract_jl: 0, qc_jl: 0,
                     pre_jl: 0, pre_contract_jl: 0, pre_qc_jl: 0,
                     end_jl: 0, end_contract_jl: 0, end_qc_jl: 0,
@@ -514,6 +518,8 @@ class StageIm {
                 this._generateZlLeafXmjData(p, im, 'gather_qty');
             }
             this._generateZlChangeData(p, im);
+            im.quantity = this.ctx.helper.add(im.quantity, p.quantity);
+
             im.jl = this.ctx.helper.add(im.jl, p.gather_qty);
             im.contract_jl = this.ctx.helper.add(im.contract_jl, p.contract_qty);
             im.qc_jl = this.ctx.helper.add(im.qc_jl, p.qc_qty);
@@ -542,6 +548,7 @@ class StageIm {
                     const im = {
                         id: this.ImData.length + 1,
                         lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, pid: pp.id,
+                        quantity: pp.quantity,
                         jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty,
                         pre_jl: pp.pre_gather_qty, pre_contract_jl: pp.pre_contract_qty, pre_qc_jl: pp.pre_qc_qty,
                         end_jl: pp.end_gather_qty, end_contract_jl: pp.end_contract_qty, end_qc_jl: pp.end_qc_qty,
@@ -568,6 +575,7 @@ class StageIm {
                 const im = {
                     id: this.ImData.length + 1,
                     lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, pid: '',
+                    quantity: p.quantity,
                     jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty,
                     pre_jl: p.pre_gather_qty, pre_contract_jl: p.pre_contract_qty, pre_qc_jl: p.pre_qc_qty,
                     end_jl: p.end_gather_qty, end_contract_jl: p.end_contract_qty, end_qc_jl: p.end_qc_qty,

+ 1 - 1
app/middleware/stage_check.js

@@ -103,7 +103,7 @@ module.exports = options => {
             this.stage = stage;
             yield next;
         } catch (err) {
-            console.log(err);
+            this.helper.log(err);
             // 输出错误到日志
             if (err.stack) {
                 this.logger.error(err);

+ 1 - 1
app/middleware/tender_select.js

@@ -46,7 +46,7 @@ module.exports = options => {
                 yield next;
             }
         } catch (err) {
-            console.log(err);
+            this.helper.log(err);
             this.redirect(this.menuList.dashboard.url);
         }
     };

+ 63 - 8
app/public/js/ledger.js

@@ -812,6 +812,35 @@ $(document).ready(function() {
                     info.cancel = !_.isEmpty(node.b_code);
                     break;
             }
+        },
+        sortCode: function (sheet) {
+            const tree = sheet.zh_tree;
+            if (!tree) return;
+
+            const select = SpreadJsObj.getSelectObject(sheet);
+            if (!select || !select.code) return;
+
+            const recursiveSortCode = function (data, parentCode, children) {
+                if (!children || children.length === 0) return;
+
+                for (const [i, child] of children.entries()) {
+                    const code = parentCode + '-' + (i + 1);
+                    const cData = tree.getNodeKeyData(child);
+                    cData.code = code;
+                    data.push(cData);
+                    if (!tree.isLeafXmj(child)) {
+                        recursiveSortCode(data, code, child.children);
+                    }
+                }
+            };
+            const data = [];
+            recursiveSortCode(data, select.code, select.children);
+            if (data.length > 0) {
+                postData(window.location.pathname + '/update', {postType: 'update', postData: data}, function (result) {
+                    const refreshNode = tree.loadPostData(result);
+                    treeOperationObj.refreshTree(sheet, refreshNode);
+                })
+            }
         }
     };
     ledgerTreeCol.initSpreadSetting(ledgerSpreadSetting);
@@ -1005,6 +1034,7 @@ $(document).ready(function() {
                         return !(valid && first && sameParent && !(first.level === 1 && first.node_type));
                     }
                 },
+                'sprBase': '-----------',
                 'copyBlock': {
                     name: '复制整块',
                     icon: 'fa-files-o',
@@ -1058,6 +1088,19 @@ $(document).ready(function() {
                         }
                     }
                 },
+                'sprBlock': '-----------',
+                'sortChildren': {
+                    name: '顺序重排子项编号',
+                    icon: 'fa-sort-numeric-asc',
+                    disabled: function (key, opt) {
+                        const node = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
+                        return !node || !node.code || !node.children || node.children === 0;
+                    },
+                    callback: function (key, opt) {
+                        treeOperationObj.sortCode(ledgerSpread.getActiveSheet());
+                    }
+                },
+                'sprSort': '-----------',
                 'batchInsert': {
                     name: '批量插入',
                     type: 'batchInsert',
@@ -1128,6 +1171,7 @@ $(document).ready(function() {
                         $('#batch').modal('show');
                     }
                 },
+                'sprBatch': '-----------',
                 'importExcel': {
                     name: '导入分项清单Excel',
                     icon: 'fa-file-excel-o',
@@ -1141,7 +1185,7 @@ $(document).ready(function() {
                                 url: '/template/导入分项清单EXCEL格式.xls',
                             },
                             callback: function (sheet) {
-                                postDataCompress(window.location.pathname + '/upload-excel', sheet, function (result) {
+                                postDataCompress(window.location.pathname + '/upload-excel/tz', sheet, function (result) {
                                     ledgerTree.loadDatas(result.bills);
                                     treeCalc.calculateAll(ledgerTree);
                                     SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
@@ -1163,23 +1207,33 @@ $(document).ready(function() {
                             || (!_.isNil(node.b_code) && node.b_code !== '');
                     },
                     callback: function (key, opt) {
+                        const node = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
                         importExcel.doImport({
                             template: {
                                 hint: '工程量清单',
                                 url: '/template/导入工程量清单EXCEL格式.xls',
                             },
                             callback: function (sheet) {
-                                postDataCompress(window.location.pathname + '/upload-excel', sheet, function (result) {
-                                    ledgerTree.loadDatas(result.bills);
-                                    treeCalc.calculateAll(ledgerTree);
-                                    SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), 'tree', ledgerTree);
-                                    pos.loadDatas(result.pos);
-                                    posOperationObj.loadCurPosData();
+                                postDataCompress(window.location.pathname + '/upload-excel/gcl2xmj', {id: node.id, sheet: sheet}, function (result) {
+                                    const ledgerSheet = ledgerSpread.getActiveSheet();
+                                    const sel = ledgerSheet.getSelections();
+
+                                    const refreshNode = ledgerTree.loadPostData(result);
+                                    treeOperationObj.refreshTree(ledgerSheet, refreshNode);
+                                    if (refreshNode.create[0]) {
+                                        if (sel && sel[0]) {
+                                            ledgerSheet.setSelection(refreshNode.create[0].index, sel[0].col, sel[0].rowCount, sel[0].colCount);
+                                        } else {
+                                            ledgerSheet.setSelection(refreshNode.create[0].index, 0, 1, 1);
+                                        }
+                                    }
+                                    treeOperationObj.refreshOperationValid(ledgerSheet);
                                 }, null);
                             }
                         });
                     }
                 },
+                'sprImport': '-----------',
                 'exportExcel': {
                     name: '导出表格数据',
                     icon: 'fa-file-excel-o',
@@ -1203,7 +1257,8 @@ $(document).ready(function() {
             },
         });
     } else {
-        SpreadJsObj.forbiddenSpreadContextMenu('#ledger-spread', ledgerSpread);
+        $('#ledger-spread').on('contextmenu', () => {return false;});
+        //SpreadJsObj.forbiddenSpreadContextMenu('#ledger-spread', ledgerSpread);
     }
 
     const posSearch = $.posSearch({selector: '#pos-search', searchSpread: posSpread});

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

@@ -858,7 +858,7 @@ const createNewPathTree = function (type, setting) {
          * @returns {boolean}
          */
         isLeafXmj(node) {
-            if (!node.code) {
+            if (node.b_code && node.b_code !== '') {
                 return false;
             }
             for (const child of node.children) {

+ 84 - 2
app/public/js/revise.js

@@ -705,6 +705,35 @@ $(document).ready(() => {
                 });
             }
         },
+        sortCode: function (sheet) {
+            const tree = sheet.zh_tree;
+            if (!tree) return;
+
+            const select = SpreadJsObj.getSelectObject(sheet);
+            if (!select || !select.code || select.code === '') return;
+
+            const recursiveSortCode = function (data, parentCode, children) {
+                if (!children || children.length === 0) return;
+
+                for (const [i, child] of children.entries()) {
+                    const code = parentCode + '-' + (i + 1);
+                    const cData = tree.getNodeKeyData(child);
+                    cData.code = code;
+                    data.push(cData);
+                    if (!tree.isLeafXmj(child)) {
+                        recursiveSortCode(data, code, child.children);
+                    }
+                }
+            };
+            const data = [];
+            recursiveSortCode(data, select.code, select.children);
+            if (data.length > 0) {
+                postData(window.location.pathname + '/update', {postType: 'update', postData: data}, function (result) {
+                    const refreshNode = tree.loadPostData(result);
+                    billsTreeSpreadObj.refreshTree(sheet, refreshNode);
+                })
+            }
+        }
     };
     billsTreeSpreadObj.refreshOperationValid(billsSheet);
     billsTreeSpreadObj.loadExprToInput(billsSheet);
@@ -856,6 +885,7 @@ $(document).ready(() => {
                         return !(valid && first && sameParent && !(first.level === 1 && first.node_type) && !nodeUsed);
                     }
                 },
+                'sprBase': '-----------',
                 'batchInsert': {
                     name: '批量插入',
                     type: 'batchInsert',
@@ -910,7 +940,56 @@ $(document).ready(() => {
                         }
                         $('#batch').modal('show');
                     }
-                }
+                },
+                'sprBatch': '-----------',
+                'sortChildren': {
+                    name: '顺序重排子项编号',
+                    icon: 'fa-sort-numeric-asc',
+                    disabled: function (key, opt) {
+                        const node = SpreadJsObj.getSelectObject(billsSheet);
+                        return !node || !node.code || !node.children || node.children === 0;
+                    },
+                    callback: function (key, opt) {
+                        billsTreeSpreadObj.sortCode(billsSheet);
+                    }
+                },
+                'sprSort': '-----------',
+                'importGclBills2Xmj': {
+                    name: '导入工程量清单至项目节',
+                    icon: 'fa-file-excel-o',
+                    disabled: function (key, opt) {
+                        const node = SpreadJsObj.getSelectObject(billsSheet);
+                        return readOnly
+                            || (node.children && node.children.length > 0)
+                            || (!_.isNil(node.b_code) && node.b_code !== '')
+                            || billsTree.checkNodeUsed(node, pos);
+                    },
+                    callback: function (key, opt) {
+                        const node = SpreadJsObj.getSelectObject(billsSheet);
+                        importExcel.doImport({
+                            template: {
+                                hint: '工程量清单',
+                                url: '/template/导入工程量清单EXCEL格式.xls',
+                            },
+                            callback: function (sheet) {
+                                postDataCompress(window.location.pathname + '/upload-excel/gcl2xmj', {id: node.id, sheet: sheet}, function (result) {
+                                    const sel = billsSheet.getSelections();
+
+                                    const refreshNode = billsTree.loadPostData(result);
+                                    billsTreeSpreadObj.refreshTree(billsSheet, refreshNode);
+                                    if (refreshNode.create[0]) {
+                                        if (sel && sel[0]) {
+                                            billsSheet.setSelection(refreshNode.create[0].index, sel[0].col, sel[0].rowCount, sel[0].colCount);
+                                        } else {
+                                            billsSheet.setSelection(refreshNode.create[0].index, 0, 1, 1);
+                                        }
+                                    }
+                                    billsTreeSpreadObj.refreshOperationValid(billsSheet);
+                                }, null);
+                            }
+                        });
+                    }
+                },
             }
         });
     }
@@ -1228,7 +1307,7 @@ $(document).ready(() => {
     posSpreadObj.loadCurPosData();
     SpreadJsObj.resetTopAndSelect(posSheet);
     posSpread.bind(spreadNS.Events.SelectionChanged, posSpreadObj.selectionChanged);
-    if (!readOnly) {
+    if (!readOnly && isTz) {
         $('#pos-expr').bind('change mouseleave', function () {
             if (this.readOnly) return;
 
@@ -1304,6 +1383,9 @@ $(document).ready(() => {
                     },
                     callback: function (key, opt) {
                         mergePeg.show();
+                    },
+                    visible: function (key, opt) {
+                        return isTz;
                     }
                 }
             }

+ 29 - 6
app/public/js/shares/merge_peg.js

@@ -47,16 +47,14 @@ const NewMergePeg = function (setting) {
                     peg = endPeg !== '' ? endPeg : '';
                 }
                 if (withPos) {
-                    peg = _.trim(sheet.getText(row, posCol)) + peg;
+                    peg += _.trim(sheet.getText(row, posCol));
                 }
                 sheet.setText(row, pegCol, peg);
             };
             if (row) {
                 const rows = row instanceof Array ? row : [row];
-                if (row instanceof Array) {
-                    for (const r of rows) {
-                        mergeRow(r)
-                    }
+                for (const r of rows) {
+                    mergeRow(r)
                 }
             } else {
                 for (let iRow = 0, iLen = sheet.getRowCount(); iRow < iLen; iRow++) {
@@ -69,7 +67,7 @@ const NewMergePeg = function (setting) {
             for (let iRow = 0, iLen = sheet.getRowCount(); iRow < iLen; iRow++) {
                 const peg = sheet.getText(iRow, pegCol);
                 if (peg !== '') {
-                    result.push({name: peg});
+                    result.push({name: peg, position: sheet.getText(iRow, posCol)});
                 }
             }
             return result;
@@ -84,6 +82,22 @@ const NewMergePeg = function (setting) {
             }
         },
         clipboardPasted: function (e, info) {
+            for (let iRow = 0; iRow < info.cellRange.rowCount; iRow++) {
+                const curRow = info.cellRange.row + iRow;
+                for (let iCol = 0; iCol < info.cellRange.colCount; iCol++) {
+                    const curCol = info.cellRange.col+ iCol;
+                    const text = info.sheet.getText(curRow, curCol);
+                    if (curCol === spCol || curCol === epCol) {
+                        if (text.length > 10) {
+                            info.sheet.setText(curRow, curCol, text.substring(0, 10));
+                        }
+                    } else if (curCol === posCol) {
+                        if (text.length > 50) {
+                            info.sheet.setText(curRow, curCol, text.substring(0, 50));
+                        }
+                    }
+                }
+            }
             spreadObj.mergePeg();
         },
         deletePress: function (sheet) {
@@ -101,6 +115,15 @@ const NewMergePeg = function (setting) {
             spreadObj.mergePeg(row);
         },
         editEnded: function (e, info) {
+            if (info.col === spCol || info.col === epCol) {
+                if (info.editingText.length > 10) {
+                    info.sheet.setText(info.row, info.col, info.editingText.substring(0, 10));
+                }
+            } else if (info.col === posCol) {
+                if (info.editingText.length > 50) {
+                    info.sheet.setText(info.row, info.col, info.editingText.substring(0, 50));
+                }
+            }
             spreadObj.mergePeg(info.row);
         },
         cut: function (sheet, sel, callback) {

+ 0 - 2
app/public/js/tender_list_manage.js

@@ -373,8 +373,6 @@ $(document).ready(() => {
     initTenderTree();
     $('.c-body').html(getTenderTreeHtml());
     bindTenderUrl();
-    console.log(tenderTree);
-    console.log(category);
     // 分类
     $('#cate-set').on('show.bs.modal', function () {
         createTree();

+ 7 - 4
app/router.js

@@ -94,7 +94,7 @@ module.exports = app => {
     app.post('/tender/:id/ledger/load', sessionAuth, tenderCheck, 'ledgerController.loadExplodeData');
     app.post('/tender/:id/ledger/get-children', sessionAuth, tenderCheck, 'ledgerController.getChildren');
     app.post('/tender/:id/ledger/update', sessionAuth, tenderCheck, 'ledgerController.update');
-    app.post('/tender/:id/ledger/upload-excel', sessionAuth, tenderCheck, 'ledgerController.uploadExcel');
+    app.post('/tender/:id/ledger/upload-excel/:ueType', sessionAuth, tenderCheck, 'ledgerController.uploadExcel');
     app.get('/tender/:id/ledger/download/:file', sessionAuth, tenderCheck, 'ledgerController.download');
     //app.post('/tender/:id/pos', sessionAuth, tenderCheck, 'ledgerController.pos');
     app.post('/tender/:id/pos/update', sessionAuth, tenderCheck, 'ledgerController.posUpdate');
@@ -105,21 +105,24 @@ module.exports = app => {
     app.post('/tender/:id/ledger/audit/delete', sessionAuth, tenderCheck, 'ledgerAuditController.remove');
     app.post('/tender/:id/ledger/audit/start', sessionAuth, tenderCheck, 'ledgerAuditController.start');
     app.post('/tender/:id/ledger/audit/check', sessionAuth, tenderCheck, 'ledgerAuditController.check');
+
     // 台账对比
     app.get('/tender/:id/ledger/gather', sessionAuth, tenderCheck, 'ledgerController.gather');
     app.post('/tender/:id/ledger/gather/load', sessionAuth, tenderCheck, 'ledgerController.loadGatherData');
+
     // 台账修订
     app.get('/tender/:id/revise', sessionAuth, tenderCheck, 'reviseController.index');
     app.post('/tender/:id/revise/add', sessionAuth, tenderCheck, 'reviseController.add');
     app.post('/tender/:id/revise/cancel', sessionAuth, tenderCheck, 'reviseController.cancel');
     app.post('/tender/:id/revise/save', sessionAuth, tenderCheck, 'reviseController.save');
-
+    // 台账修订页面
     app.get('/tender/:id/revise/info', sessionAuth, tenderCheck, 'reviseController.info');
     app.post('/tender/:id/revise/info/update', sessionAuth, tenderCheck, 'reviseController.update');
-
+    app.post('/tender/:id/revise/info/upload-excel/:ueType', sessionAuth, tenderCheck, 'reviseController.uploadExcel');
+    // 查看修订数据
     app.get('/tender/:id/revise/history', sessionAuth, tenderCheck, 'reviseController.history');
     app.post('/tender/:id/revise/history/info', sessionAuth, tenderCheck, 'reviseController.historyInfo');
-
+    // 修订审批
     app.post('/tender/:id/revise/audit/add', sessionAuth, tenderCheck, 'reviseController.addAuditor');
     app.post('/tender/:id/revise/audit/remove', sessionAuth, tenderCheck, 'reviseController.removeAuditor');
     app.post('/tender/:id/revise/audit/start', sessionAuth, tenderCheck, 'reviseController.start');

+ 1 - 161
app/service/ledger.js

@@ -282,43 +282,6 @@ module.exports = app => {
             await this.ctx.service.pos.deletePosData(this.transaction, mid, this._.map(deleteData, 'id'));
         }
 
-        /**
-         * 过滤data中update方式不可提交的字段
-         * @param {Number} id - 主键key
-         * @param {Object} data
-         * @return {Object<{id: *}>}
-         * @private
-         */
-        // _filterUpdateInvalidField(id, data) {
-        //     const result = {
-        //         id,
-        //     };
-        //     for (const prop in data) {
-        //         if (readOnlyFields.indexOf(prop) === -1) {
-        //             result[prop] = data[prop];
-        //         }
-        //     }
-        //     return result;
-        // }
-
-        /**
-         * newData中,以orgData为基准,过滤掉orgData中未定义或值相等的部分
-         * @param {Object} orgData
-         * @param {Object} newData
-         * @private
-         */
-        _filterChangedField(orgData, newData) {
-            const result = {};
-            let bChanged = false;
-            for (const prop in orgData) {
-                if (this._.isEmpty(newData[prop]) && newData[prop] !== orgData[prop]) {
-                    result[prop] = newData[prop];
-                    bChanged = true;
-                }
-            }
-            return bChanged ? result : undefined;
-        }
-
         _checkField(data, field) {
             const fields = field instanceof Array ? field : [field];
             for (const prop in data) {
@@ -330,21 +293,6 @@ module.exports = app => {
         }
 
         /**
-         * 检查data中是否含有计算字段
-         * @param {Object} data
-         * @return {boolean}
-         * @private
-         */
-        // _checkCalcField(data) {
-        //     for (const prop in data) {
-        //         if (calcFields.indexOf(prop) >= 0) {
-        //             return true;
-        //         }
-        //     }
-        //     return false;
-        // }
-
-        /**
          * 复制粘贴整块
          * @param {Number} tenderId - 标段Id
          * @param {Number} selectId - 选中几点Id
@@ -451,103 +399,6 @@ module.exports = app => {
         }
 
         /**
-         * 提交数据 - 响应计算(增量方式计算)
-         * @param {Number} tenderId
-         * @param {Object} data
-         * @return {Promise<*>}
-         */
-        // async updateCalc(tenderId, data) {
-        //     // 简单验证数据
-        //     if (tenderId <= 0 || !this.ctx.tender) {
-        //         throw '标段不存在';
-        //     }
-        //     const info = this.ctx.tender.info;
-        //     if (!data) {
-        //         throw '提交数据错误';
-        //     }
-        //     const datas = data instanceof Array ? data : [data];
-        //     const ids = [];
-        //     for (const row of datas) {
-        //         if (tenderId !== row.tender_id) {
-        //             throw '提交数据错误';
-        //         }
-        //         ids.push(row.id);
-        //     }
-        //
-        //     this.transaction = await this.db.beginTransaction();
-        //     try {
-        //         for (const row of datas) {
-        //             const updateNode = await this.getDataById(row.id);
-        //             if (!updateNode || tenderId !== updateNode.tender_id || row.ledger_id !== updateNode.ledger_id) {
-        //                 throw '提交数据错误';
-        //             }
-        //             let updateData;
-        //             if (row.unit) {
-        //                 if (row.sgfh_qty === undefined) { row.sgfh_qty = updateNode.sgfh_qty; }
-        //                 if (row.sjcl_qty === undefined) { row.sjcl_qty = updateNode.sjcl_qty; }
-        //                 if (row.qtcl_qty === undefined) { row.qtcl_qty = updateNode.qtcl_qty; }
-        //                 if (row.deal_qty === undefined) { row.deal_qty = updateNode.deal_qty; }
-        //             }
-        //             if (row.b_code) {
-        //                 row.dgn_qty1 = null;
-        //                 row.dgn_qty2 = null;
-        //             }
-        //             if (this._checkCalcField(row)) {
-        //                 let calcData = JSON.parse(JSON.stringify(row));
-        //                 const precision = this.ctx.helper.findPrecision(info.precision, row.unit ? row.unit : updateNode.unit);
-        //                 // 数量保留小数位数
-        //                 this.ctx.helper.checkFieldPrecision(calcData, qtyFields, precision.value);
-        //                 // 单位保留小数位数
-        //                 this.ctx.helper.checkFieldPrecision(calcData, upFields, info.decimal.up);
-        //                 // 未提交单价则读取数据库单价
-        //                 if (row.unit_price === undefined) calcData.unit_price = updateNode.unit_price;
-        //                 // 计算
-        //                 if (row.sgfh_qty !== undefined || row.sjcl_qty !== undefined || row.qtcl_qty !== undefined ||
-        //                     row.deal_qty !== undefined || row.unit_price) {
-        //                     if (row.sgfh_qty === undefined) calcData.sgfh_qty = updateNode.sgfh_qty;
-        //                     if (row.sjcl_qty === undefined) calcData.sjcl_qty = updateNode.sjcl_qty;
-        //                     if (row.qtcl_qty === undefined) calcData.qtcl_qty = updateNode.qtcl_qty;
-        //                     if (row.deal_qty === undefined) calcData.deal_qty = updateNode.deal_qty;
-        //                     calcData.quantity = this.ctx.helper.sum([calcData.sgfh_qty, calcData.sjcl_qty, calcData.qtcl_qty]);
-        //                     calcData.sgfh_tp = this.ctx.helper.mul(calcData.sgfh_qty, calcData.unit_price, info.decimal.tp);
-        //                     calcData.sjcl_tp = this.ctx.helper.mul(calcData.sjcl_qty, calcData.unit_price, info.decimal.tp);
-        //                     calcData.qtcl_tp = this.ctx.helper.mul(calcData.qtcl_qty, calcData.unit_price, info.decimal.tp);
-        //                     calcData.total_price = this.ctx.helper.mul(calcData.quantity, calcData.unit_price, info.decimal.tp);
-        //                     calcData.deal_tp = this.ctx.helper.mul(calcData.deal_qty, calcData.unit_price, info.decimal.tp);
-        //                 } else if (row.sgfh_tp !== undefined || row.sjcl_tp !== undefined || row.qtcl_tp !== undefined || row.deal_tp !== undefined) {
-        //                     calcData.sgfh_qty = null;
-        //                     calcData.sjcl_qty = null;
-        //                     calcData.qtcl_qty = null;
-        //                     calcData.quantity = null;
-        //                     calcData.deal_qty = null;
-        //                     calcData.sgfh_tp = (row.sgfh_tp !== undefined) ? this.ctx.helper.round(calcData.row.sgfh_tp, info.decimal.tp) : updateNode.sgfh_tp;
-        //                     calcData.sjcl_tp = (row.sgfh_tp !== undefined) ? this.ctx.helper.round(calcData.row.sjcl_tp, info.decimal.tp) : updateNode.sjcl_tp;
-        //                     calcData.qtcl_tp = (row.sgfh_tp !== undefined) ? this.ctx.helper.round(calcData.row.qtcl_tp, info.decimal.tp) : updateNode.qtcl_tp;
-        //                     calcData.total_price = this.ctx.helper.sum([calcData.sgfh_tp, calcData.sjcl_tp, calcData.qtcl_tp]);
-        //                     calcData.deal_tp = (row.deal_tp !== undefined) ? this.ctx.helper.round(calcData.row.deal_tp, info.decimal.tp) : updateNode.deal_tp;
-        //                 } else if (row.unit_price !== undefined) {
-        //                     calcData.sgfh_tp = this.ctx.helper.mul(calcData.sgfh_qty, calcData.unit_price, info.decimal.tp);
-        //                     calcData.sjcl_tp = this.ctx.helper.mul(calcData.sjcl_qty, calcData.unit_price, info.decimal.tp);
-        //                     calcData.qtcl_tp = this.ctx.helper.mul(calcData.qtcl_qty, calcData.unit_price, info.decimal.tp);
-        //                     calcData.total_price = this.ctx.helper.mul(calcData.quantity, calcData.unit_price, info.decimal.tp);
-        //                     calcData.deal_tp = this.ctx.helper.mul(calcData.deal_qty, calcData.unit_price, info.decimal.tp);
-        //                 }
-        //                 updateData = this._filterUpdateInvalidField(updateNode.id, calcData);
-        //             } else {
-        //                 updateData = this._filterUpdateInvalidField(updateNode.id, row);
-        //             }
-        //             await this.transaction.update(this.tableName, updateData);
-        //         }
-        //         await this.transaction.commit();
-        //     } catch (err) {
-        //         await this.transaction.rollback();
-        //         throw err;
-        //     }
-        //
-        //     return { update: await this.getDataByIds(ids) };
-        // }
-
-        /**
          *
          * @param tenderId
          * @param xmj
@@ -821,24 +672,16 @@ module.exports = app => {
          * @returns {Promise<void>}
          */
         async importExcel(templateId, excelData) {
-            console.time('analysis');
-            const AnalysisExcel = require('../lib/analysis_excel');
+            const AnalysisExcel = require('../lib/analysis_excel').AnalysisExcelTree;
             const analysisExcel = new AnalysisExcel(this.ctx);
             const tempData = await this.ctx.service.tenderNodeTemplate.getData(templateId, true);
             const cacheTree = analysisExcel.analysisData(excelData, tempData);
             const cacheKey = keyPre + this.ctx.tender.id;
             const orgMaxId = parseInt(await this.cache.get(cacheKey));
-            console.timeEnd('analysis');
             const transaction = await this.db.beginTransaction();
             try {
-                console.time('deleteBills');
                 await transaction.delete(this.tableName, {tender_id: this.ctx.tender.id});
-                console.timeEnd('deleteBills');
-                console.time('deletePos');
                 await transaction.delete(this.ctx.service.pos.tableName, {tid: this.ctx.tender.id});
-                console.timeEnd('deletePos');
-                console.time('insertBills');
-                //const bills = await this._importCacheTreeNodes(transaction, cacheTree.items);
                 const datas = [];
                 for (const node of cacheTree.items) {
                     datas.push({
@@ -866,12 +709,9 @@ module.exports = app => {
                     });
                 }
                 await transaction.insert(this.tableName, datas);
-                console.timeEnd('insertBills');
-                console.time('insertPos');
                 if (cacheTree.pos && cacheTree.pos.length > 0) {
                     await transaction.insert(this.ctx.service.pos.tableName, cacheTree.pos);
                 }
-                console.timeEnd('insertPos');
                 await transaction.commit();
                 this.cache.set(cacheKey, cacheTree.items.length + 1, 'EX', this.ctx.app.config.cacheTime);
                 return {bills: datas, pos: cacheTree.pos}

+ 2 - 2
app/service/ledger_revise.js

@@ -100,9 +100,9 @@ module.exports = app => {
         async _initRevisePos(transaction, tid) {
             const sql = 'Insert Into ' + this.ctx.service.revisePos.tableName +
                 '  (id, tid, lid, name, drawing_code, quantity, add_stage, add_times, add_user,' +
-                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, in_time, porder)' +
+                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, in_time, porder, position)' +
                 '  Select id, tid, lid, name, drawing_code, quantity, add_stage, add_times, add_user,' +
-                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, in_time, porder' +
+                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, in_time, porder, position' +
                 '  From ' + this.ctx.service.pos.tableName +
                 '  Where `tid` = ?';
             const sqlParam = [tid];

+ 3 - 3
app/service/pos.js

@@ -25,13 +25,13 @@ module.exports = app => {
         async getPosData(condition) {
             return await this.db.select(this.tableName, {
                 where: condition,
-                columns: ['id', 'tid', 'lid', 'name', 'quantity', 'drawing_code', 'sgfh_qty', 'sjcl_qty', 'qtcl_qty', 'in_time', 'porder', 'add_stage'],
+                columns: ['id', 'tid', 'lid', 'name', 'quantity', 'position', 'drawing_code', 'sgfh_qty', 'sjcl_qty', 'qtcl_qty', 'in_time', 'porder', 'add_stage'],
                 order: [['porder', 'ASC']],
             });
         }
 
         async getPosDataWithAddStageOrder(condition) {
-            const sql = 'SELECT p.id, p.tid, p.lid, p.name, p.quantity, p.drawing_code, p.sgfh_qty, p.sjcl_qty, p.qtcl_qty, p.porder, p.add_stage, p.add_times, p.add_user, s.order As add_stage_order ' +
+            const sql = 'SELECT p.id, p.tid, p.lid, p.name, p.quantity, p.position, p.drawing_code, p.sgfh_qty, p.sjcl_qty, p.qtcl_qty, p.porder, p.add_stage, p.add_times, p.add_user, s.order As add_stage_order ' +
                 '  FROM ' + this.tableName + ' p ' +
                 '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s' +
                 '  ON p.add_stage = s.id'
@@ -41,7 +41,7 @@ module.exports = app => {
 
         async getPosDataByIds(ids) {
             if (ids instanceof Array && ids.length > 0) {
-                const sql = 'SELECT id, tid, lid, name, quantity, drawing_code, sgfh_qty, sjcl_qty, qtcl_qty, add_stage, add_times, add_user' +
+                const sql = 'SELECT id, tid, lid, name, quantity, position, drawing_code, sgfh_qty, sjcl_qty, qtcl_qty, add_stage, add_times, add_user' +
                     '  FROM ' + this.tableName +
                     '  WHERE id in (' + this.ctx.helper.getInArrStrSqlFilter(ids) + ')';
                 return await this.db.query(sql, []);

+ 11 - 10
app/service/report_memory.js

@@ -17,6 +17,7 @@ const audit = require('../const/audit');
 const stageImTz = 'mem_stage_im_tz';
 const stageImTzBills = 'mem_stage_im_tz_bills';
 const stageImZl = 'mem_stage_im_zl';
+const stageImVersion = '1.0';
 
 module.exports = app => {
     class ReportMemory extends app.BaseService {
@@ -39,9 +40,9 @@ module.exports = app => {
         // 1. 达到redis内存阈值时,数据会swap到磁盘,此时将消耗IO时间
         // 2. redis单独服务器
         // 3. redis集群
-        async _getReportMemoryCache(name, tid, sid, time) {
+        async _getReportMemoryCache(name, tid, sid, time, version = '') {
             // redis
-            const cacheKey = name + '-t' + tid + (sid ? '-s' + sid : '') + (time ? '-' + time : '');
+            const cacheKey = name + '-t' + tid + (sid ? '-s' + sid : '') + (time ? '-' + time : '') + version;
             const data = await this.cache.get(cacheKey);
             if (data) {
                 return eval(data);
@@ -64,9 +65,9 @@ module.exports = app => {
             // }
         }
 
-        async _setReportMemoryCache(name, tid, sid, time, data) {
+        async _setReportMemoryCache(name, tid, sid, time, data, version = '') {
             // redis
-            const cacheKey = name + '-t' + tid + (sid ? '-s' + sid : '') + (time ? '-' + time : '');
+            const cacheKey = name + '-t' + tid + (sid ? '-s' + sid : '') + (time ? '-' + time : '') + version;
             this.cache.set(cacheKey, JSON.stringify(data), 'EX', this.ctx.app.config.cacheTime);
 
             // mysql + IO
@@ -93,10 +94,10 @@ module.exports = app => {
             this.stageImData.main = stageIm.ImData;
             if (isTz) {
                 this.stageImData.bills = stageIm.ImBillsData;
-                await this._setReportMemoryCache(stageImTz, tid, sid, this.ctx.stage.cacheTime, this.stageImData.main);
-                await this._setReportMemoryCache(stageImTzBills, tid, sid, this.ctx.stage.cacheTime, this.stageImData.bills);
+                await this._setReportMemoryCache(stageImTz, tid, sid, this.ctx.stage.cacheTime, this.stageImData.main, stageImVersion);
+                await this._setReportMemoryCache(stageImTzBills, tid, sid, this.ctx.stage.cacheTime, this.stageImData.bills, stageImVersion);
             } else {
-                await this._setReportMemoryCache(stageImZl, tid, sid, this.ctx.stage.cacheTime, this.stageImData.main);
+                await this._setReportMemoryCache(stageImZl, tid, sid, this.ctx.stage.cacheTime, this.stageImData.main, stageImVersion);
             }
         }
 
@@ -127,7 +128,7 @@ module.exports = app => {
         async getStageImTzData(tid, sid) {
             await this.ctx.service.tender.checkTender(tid);
             await this.ctx.service.stage.checkStage(sid);
-            const cache = await this._getReportMemoryCache('mem_stage_im_tz', tid, sid, this.ctx.stage.cacheTime);
+            const cache = await this._getReportMemoryCache('mem_stage_im_tz', tid, sid, this.ctx.stage.cacheTime, stageImVersion);
             if (cache) {
                 // console.log('cache');
                 return cache;
@@ -152,7 +153,7 @@ module.exports = app => {
         async getStageImTzBillsData(tid, sid) {
             await this.ctx.service.tender.checkTender(tid);
             await this.ctx.service.stage.checkStage(sid);
-            const cache = await this._getReportMemoryCache('mem_stage_im_tz_bills', tid, sid, this.ctx.stage.cacheTime);
+            const cache = await this._getReportMemoryCache('mem_stage_im_tz_bills', tid, sid, this.ctx.stage.cacheTime, stageImVersion);
             if (cache) return cache;
 
             if (!this.stageImData) {
@@ -173,7 +174,7 @@ module.exports = app => {
         async getStageImZlData(tid, sid) {
             await this.ctx.service.tender.checkTender(tid);
             await this.ctx.service.stage.checkStage(sid);
-            const cache = await this._getReportMemoryCache('mem_stage_im_zl', tid, sid, this.ctx.stage.cacheTime);
+            const cache = await this._getReportMemoryCache('mem_stage_im_zl', tid, sid, this.ctx.stage.cacheTime, stageImVersion);
             if (cache) return cache;
 
             this.stageImData = {};

+ 2 - 2
app/service/revise_audit.js

@@ -236,9 +236,9 @@ module.exports = app => {
             await transaction.delete(this.ctx.service.pos.tableName, {tid: revise.tid});
             const pSql = 'Insert Into ' + this.ctx.service.pos.tableName +
                 '  (id, tid, lid, name, drawing_code, quantity, add_stage, add_times, add_user,' +
-                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder)' +
+                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder, position)' +
                 '  Select id, tid, lid, name, drawing_code, quantity, add_stage, add_times, add_user,' +
-                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder' +
+                '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder, position' +
                 '  From ' + this.ctx.service.revisePos.tableName +
                 '  Where `tid` = ?';
             await transaction.query(pSql, sqlParam);

+ 1 - 1
app/service/revise_pos.js

@@ -23,7 +23,7 @@ module.exports = app => {
         }
 
         async getPosData(condition) {
-            const sql = 'SELECT p.id, p.tid, p.lid, p.name, p.quantity, p.drawing_code, p.sgfh_qty, p.sjcl_qty, p.qtcl_qty, p.porder, p.add_stage, p.add_times, p.add_user, s.order As add_stage_order ' +
+            const sql = 'SELECT p.id, p.tid, p.lid, p.name, p.quantity, p.position, p.drawing_code, p.sgfh_qty, p.sjcl_qty, p.qtcl_qty, p.porder, p.add_stage, p.add_times, p.add_user, s.order As add_stage_order ' +
                 '  FROM ' + this.tableName + ' p ' +
                 '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s' +
                 '  ON add_stage = s.id'

+ 0 - 2
app/service/stage_pay.js

@@ -93,7 +93,6 @@ module.exports = app => {
                     throw '标段数据有误';
                 }
                 const prePays = await this.getStageLastestPays(preStage.id);
-                console.log(prePays.length);
                 for (const pp of prePays) {
                     const p = this._.find(pays, {id: pp.pid});
                     stagePays.push({
@@ -105,7 +104,6 @@ module.exports = app => {
                         pre_finish: pp.pre_finish || (pp.rprice ? pp.end_tp === pp.rprice : false),
                     });
                 }
-                console.log(stagePays.length);
             } else {
                 for (const p of pays) {
                     stagePays.push({

+ 1 - 1
app/service/stage_pos.js

@@ -161,7 +161,7 @@ module.exports = app => {
                     }
                     // 在主表pos中新增数据
                     const p = {
-                        id: this.uuid.v4(), tid: this.ctx.tender.id, lid: d.lid, name: d.name, porder: d.porder,
+                        id: this.uuid.v4(), tid: this.ctx.tender.id, lid: d.lid, name: d.name, porder: d.porder, position: d.position,
                         add_stage: this.ctx.stage.id,
                         add_times: this.ctx.stage.curTimes,
                         add_user: this.ctx.session.sessionUser.accountId,

+ 1 - 1
app/service/tender.js

@@ -291,7 +291,7 @@ module.exports = app => {
                 await transaction.commit();
                 return true;
             } catch (err) {
-                console.log(err);
+                this.ctx.helper.log(err);
                 await transaction.rollback();
                 return false;
             }

+ 2 - 0
app/view/revise/history.ejs

@@ -39,6 +39,7 @@
                 <!--0号台帐模式-->
                 <div class="sjs-height-1" style="overflow: hidden" id="bills-spread">
                 </div>
+                <% if (ctx.tender.data.measure_type === measureType.tz.value) { %>
                 <div class="bcontent-wrap">
                     <div id="revise-resize" class="resize-y" id="top-spr" r-Type="height" div1=".sjs-height-1" div2=".bcontent-wrap" title="调整大小"><!--调整上下高度条--></div>
                     <div class="bc-bar mb-1">
@@ -53,6 +54,7 @@
                     <div class="sp-wrap" id="pos-spread">
                     </div>
                 </div>
+                <% } %>
             </div>
             <!--右栏-->
             <div class="c-body" id="right-view" style="display: none; width: 33%;">

+ 2 - 0
app/view/revise/info.ejs

@@ -75,6 +75,7 @@
                 <!--0号台帐模式-->
                 <div class="sjs-height-1" style="overflow: hidden" id="bills-spread">
                 </div>
+                <% if (ctx.tender.data.measure_type === measureType.tz.value) { %>
                 <div class="bcontent-wrap">
                     <div id="revise-resize" class="resize-y" id="top-spr" r-Type="height" div1=".sjs-height-1" div2=".bcontent-wrap" title="调整大小"><!--调整上下高度条--></div>
                     <div class="bc-bar mb-1">
@@ -99,6 +100,7 @@
                     <div class="sp-wrap" id="pos-spread">
                     </div>
                 </div>
+                <% } %>
             </div>
             <!--右栏-->
             <div class="c-body" id="right-view" style="display: none; width: 33%;">

+ 1 - 0
app/view/revise/info_modal.ejs

@@ -477,6 +477,7 @@
 </div>
 <% } %>
 <% include ../shares/merge_peg_modal.ejs %>
+<% include ../shares/import_excel_modal.ejs %>
 <script>
     <% if (ctx.session.sessionUser.accountId === revise.uid && (revise.status === audit.status.uncheck || revise.status === audit.status.checkNo)) { %>
     const accountList = JSON.parse('<%- JSON.stringify(accountList) %>');

+ 16 - 13
app/view/shares/import_excel_modal.ejs

@@ -1,3 +1,4 @@
+<!--依赖xlsx/jQuery-->
 <!--导入清单Excel-->
 <div class="modal fade" id="import-excel" data-backdrop="static" enctype="multipart/form-data">
     <div class="modal-dialog" role="document">
@@ -25,6 +26,7 @@
 </div>
 <script>
     const importExcel = (function () {
+        let callback;
         // 选择excel文件后,加载全部sheet
         $('#import-excel-file').change(function () {
             if (this.files.length === 0) {
@@ -68,24 +70,24 @@
             }
         });
         // 清除上一次数据
-        $('#upload-ledger').bind('hidden.bs.modal', function () {
+        $('#import-excel').bind('hidden.bs.modal', function () {
             $('#import-excel-file').val('');
             $('#excel-sheets').html('');
         });
 
+        // 上传excel内容,并导入
+        $('#import-excel-ok').click(function () {
+            const sheetName = $('input[name=sheetName]:checked').val();
+            if (sheetName) {
+                const sheet = {
+                    rows: xlsxUtils.getSheetByName(sheetName, {header: 1}),
+                    merge: xlsxUtils._wb.Sheets[sheetName]["!merges"]
+                };
+                if (callback) callback(sheet);
+                $('#import-excel').modal('hide');
+            }
+        });
         const doImport = function (setting) {
-            // 上传excel内容,并导入
-            $('#import-excel-ok').click(function () {
-                const sheetName = $('input[name=sheetName]:checked').val();
-                if (sheetName) {
-                    const sheet = {
-                        rows: xlsxUtils.getSheetByName(sheetName, {header: 1}),
-                        merge: xlsxUtils._wb.Sheets[sheetName]["!merges"]
-                    };
-                    setting.callback(sheet);
-                    $('#import-excel').modal('hide');
-                }
-            });
             if (setting.template) {
                 $('#import-template').show();
                 $('#import-type-hint').html(setting.template.hint);
@@ -94,6 +96,7 @@
                 $('#import-template').hide();
             }
             $('#import-excel').modal('show');
+            callback = setting.callback;
         }
         return { doImport };
     })();

+ 2 - 0
config/web.js

@@ -195,6 +195,8 @@ const JsFiles = {
         revise: {
             info: {
                 files: [
+                    "/public/js/js-xlsx/xlsx.full.min.js",
+                    "/public/js/js-xlsx/xlsx.utils.js",
                     "/public/js/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js",
                     "/public/js/decimal.min.js",
                     "/public/js/math.min.js",