浏览代码

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

TonyKang 5 年之前
父节点
当前提交
c308de5434

+ 1 - 1
app/base/base_bills_service.js

@@ -35,7 +35,6 @@ class BaseBillsSerivce extends TreeService {
         data.deal_tp = null;
     }
 
-
     /**
      * 从标准数据中提取有效数据
      * @param {Object} stdData - 从标准库中查询所得
@@ -465,6 +464,7 @@ class BaseBillsSerivce extends TreeService {
         const AnalysisExcel = require('../lib/analysis_excel').AnalysisGclExcelTree;
         const analysisExcel = new AnalysisExcel(this.ctx);
         const cacheData = analysisExcel.analysisData(sheet, node, maxId, data);
+        if (!cacheData) throw '导入数据错误,请检查Excel文件后重试';
 
         const datas = [];
         for (const node of cacheData.items) {

+ 33 - 1
app/controller/spss_controller.js

@@ -27,7 +27,6 @@ module.exports = app => {
         }
 
         async _getTzData(tid, includePos = false) {
-            console.log(tid);
             const tender = await this.ctx.service.tender.getTender(tid);
             if (!tender || tender.project_id !== this.ctx.session.sessionProject.id) {
                 throw '不存在该标段';
@@ -257,6 +256,39 @@ module.exports = app => {
                 ctx.body = this.ajaxErrorBody(err, '查询数据错误');
             }
         }
+        /**
+         * 检测台账 页面
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async checkTz(ctx) {
+            try {
+                const renderData = {
+                    jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tools.checkTz)
+                };
+                await this.layout('spss/check_tz.ejs', renderData);
+            } catch (err) {
+                ctx.helper.log(err);
+            }
+        }
+        /**
+         * 获取 期计量 汇总 数据(Ajax)
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async loadBaseData(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const responseData = {err: 0, msg: '', data: []};
+
+                responseData.data = await this._getTzData(data.id);
+                ctx.body = responseData;
+            } catch (err) {
+                ctx.helper.log(err);
+                ctx.body = this.ajaxErrorBody(err, '查询数据错误');
+            }
+        }
     }
 
     return SpssController;

+ 1 - 0
app/lib/analysis_excel.js

@@ -21,6 +21,7 @@ const aeUtils = {
         const colsDef = {};
         for (const iCol in row) {
             const text = row[iCol];
+            if (text === null) continue;
             for (const header in colHeaderMatch) {
                 const match = colHeaderMatch[header];
                 switch (match.type) {

+ 0 - 5
app/lib/rpt_data_analysis.js

@@ -1010,11 +1010,6 @@ const auditSelect = {
             for (const asc of asCustom) {
                 order.push(asc.order);
             }
-        } else {
-            const setting = JSON.stringify(asDefine.setting);
-            for (const [i, s] of setting.select.entries()) {
-                order.push(i);
-            }
         }
 
         for (const t of options.table) {

+ 7 - 3
app/public/js/change_set.js

@@ -374,7 +374,13 @@ $(document).ready(() => {
         const isDeal = $(this).data('gcl') !== undefined ? true : false;
         let codeHtml = '<tr quantity="'+ $(this).children('td').eq(5).text() +'"><td colspan="4" class="colspan_1">&nbsp;</td><td class="colspan_2"><input type="checkbox"></td></tr>';
         if (isDeal) {
-            const gcl = gclGatherData[$(this).data('gcl')];
+            const lid = $(this).data('lid');
+            let gcl = _.find(gclGatherData, function (item) {
+                return item.leafXmjs && item.leafXmjs[0].gcl_id === lid;
+            });
+            if (!gcl) {
+                gcl = gclGatherData[$(this).data('gcl')];
+            }
             codeHtml = '';
             for (const leaf of gcl.leafXmjs) {
                 const quantity = leaf.quantity !== undefined && leaf.quantity !== null ? leaf.quantity : 0;
@@ -615,8 +621,6 @@ function tableDataRemake(changeListData) {
             //     toastr.warning('台账清单列表已不存在'+ clinfo[0] +',故删除之');
             //     continue;
             // }
-            console.log(listinfo);
-            console.log(clinfo);
             if (listinfo === undefined) {
                 // 针对旧数据获取清单信息
                 listinfo = changeListData[clinfo[8] - 1];

+ 229 - 0
app/public/js/spss_check_tz.js

@@ -0,0 +1,229 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+$(document).ready(function () {
+    const error = {
+        repeatBills: [],
+    };
+    autoFlashHeight();
+    // 根据设置整理Spread设置
+    const ledgerSpreadSetting = {
+        cols: [
+            {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', cellType: 'tree'},
+            {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@'},
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@'},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number'},
+            {title: '项目节数量|数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|数量2',  colSpan: '|1', rowSpan: '|1', field: 'dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
+            {title: '经济指标',  colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '设计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sgfh_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sgfh_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '设计错漏增减|数量', colSpan: '2|1', rowSpan: '1|1', field: 'sjcl_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'sjcl_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '其他错漏增减|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qtcl_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qtcl_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '台账小计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'}
+        ],
+        emptyRows: 2,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+    };
+    const posSpreadSetting = {
+        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'},
+            {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
+        ],
+        emptyRows: 3,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+    };
+    // 初始化台账
+    const billsSpread = SpreadJsObj.createNewSpread($('#bills-spread')[0]);
+    const billsSheet = billsSpread.getActiveSheet();
+    SpreadJsObj.initSheet(billsSheet, ledgerSpreadSetting);
+    // 初始化部位
+    const posSpread = SpreadJsObj.createNewSpread($('#pos-spread')[0]);
+    const posSheet = posSpread.getActiveSheet();
+    SpreadJsObj.initSheet(posSheet, posSpreadSetting);
+
+    const billsTree = createNewPathTree('ledger', {
+        id: 'ledger_id',
+        pid: 'ledger_pid',
+        order: 'order',
+        level: 'level',
+        rootId: -1,
+        keys: ['id', 'tender_id', 'ledger_id'],
+        calcFields: ['deal_tp', 'sgfh_tp', 'sjcl_tp', 'qtcl_tp', 'total_price'],
+    });
+    const pos = new PosData({
+        id: 'id', ledgerId: 'lid',
+    });
+
+    // 获取部位明细数据
+    function loadPosData(iRow) {
+        if (!billsSheet.zh_tree) return;
+        const node = billsSheet.zh_tree.nodes[iRow];
+        if (node) {
+            SpreadJsObj.loadSheetData(posSheet, SpreadJsObj.DataType.Data, node.pos);
+        } else {
+            SpreadJsObj.loadSheetData(posSheet, SpreadJsObj.DataType.Data, []);
+        }
+        SpreadJsObj.resetTopAndSelect(posSheet);
+    }
+    // 切换清单行,读取所属项目节数据
+    billsSheet.bind(spreadNS.Events.SelectionChanged, function (e, info) {
+        if (info.newSelections) {
+            const iNewRow = info.newSelections[0].row;
+            if (info.oldSelections) {
+                const iOldRow = info.oldSelections[0].row;
+                if (iNewRow !== iOldRow) {
+                    loadPosData(iNewRow);
+                }
+            } else {
+                loadPosData(iNewRow);
+            }
+        }
+    });
+
+    // 右键
+    $.contextMenu({
+        selector: '#bills-spread',
+        build: function ($trigger, e) {
+            const target = SpreadJsObj.safeRightClickSelection($trigger, e, billsSpread);
+            return target.hitTestType === spreadNS.SheetArea.viewport || target.hitTestType === spreadNS.SheetArea.rowHeader;
+        },
+        items: {
+            checkInvisibleNode: {
+                name: '检查是否存在不可见节点',
+                icon: '',
+                callback: function (key, opt) {
+                    if (error.repeatBills.length === 0) {
+                        toastr.success('不存在不可见节点');
+                    } else {
+                        toastr.warning('存在不可见节点,详细见控制台打印');
+                        console.log('存在' + error.repeatBills.length + '个节点,无法加载至树结构:');
+                        const sql = [];
+                        for (const b of error.repeatBills) {
+                            console.log(b);
+                            sql.push("Delete From `zh_ledger` Where id = '" + b.id + "';");
+                        }
+                        console.log('可使用如下sql修复:');
+                        console.log(sql.join('\n'));
+                        console.log('如果标段已上报,请再使用以下sql更新缓存:');
+                        console.log('\n' +
+                            'Update `zh_tender` t\n' +
+                            'INNER JOIN (Select Sum(`total_price`) as tp, Max(`tender_id`) as id From `zh_ledger` where `tender_id` = \' + billsTree.datas[0].tender_id + \') c\n' +
+                            'ON t.id = c.id\n' +
+                            'Set t.`total_price` = c.tp');
+                    }
+                },
+            }
+        },
+    });
+
+    // 选择
+    $('#load-tz').click(function () {
+        try {
+            const id = parseInt($('input[name=tz-id]').val());
+            if (id <= 0) return;
+            postData('/tools/load', {id: id}, function (result) {
+                billsTree.loadDatas(result.bills);
+                treeCalc.calculateAll(billsTree);
+                SpreadJsObj.loadSheetData(billsSheet, 'tree', billsTree);
+
+                for (const b of result.bills) {
+                    const node = billsTree.getItems(b.ledger_id);
+                    if (!node || node.id !== b.id) error.repeatBills.push(b);
+                }
+
+                pos.loadDatas(result.pos);
+                loadPosData();
+            });
+        } catch (err) {
+            toastr.error('输入的标段ID非法');
+        }
+    });
+    // 显示层次
+    (function (select, sheet) {
+        $(select).click(function () {
+            if (!sheet.zh_tree) return;
+            const tag = $(this).attr('tag');
+            const tree = sheet.zh_tree;
+            switch (tag) {
+                case "1":
+                case "2":
+                case "3":
+                case "4":
+                case "5":
+                    tree.expandByLevel(parseInt(tag));
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+                case "last":
+                    tree.expandByCustom(() => { return true; });
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+                case "leafXmj":
+                    tree.expandToLeafXmj();
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+                case "curMeasure":
+                    tree.expandByCalcFields();
+                    SpreadJsObj.refreshTreeRowVisible(sheet);
+                    break;
+            }
+        });
+    })('a[name=showLevel]', billsSheet);
+    // 导航栏
+    $.subMenu({
+        menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
+        toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',
+        key: 'menu.1.0.0',
+        miniHint: '#sub-mini-hint', hintKey: 'menu.hint.1.0.1',
+        callback: function (info) {
+            if (info.mini) {
+                $('.panel-title').addClass('fluid');
+                $('#sub-menu').removeClass('panel-sidebar');
+            } else {
+                $('.panel-title').removeClass('fluid');
+                $('#sub-menu').addClass('panel-sidebar');
+            }
+            autoFlashHeight();
+            billsSpread.refresh();
+            posSpread.refresh();
+        }
+    });
+    // 上下窗口resizer
+    $.divResizer({
+        select: '#main-resize',
+        callback: function () {
+            billsSpread.refresh();
+            let bcontent = $(".bcontent-wrap").length > 0 ? $(".bcontent-wrap").height() : 0;
+            $(".sp-wrap").height(bcontent - 30);
+            posSpread.refresh();
+        }
+    });
+});

+ 2 - 0
app/router.js

@@ -317,6 +317,8 @@ module.exports = app => {
     app.post('/gather/tz/load', sessionAuth, 'spssController.loadGatherTz');
     app.get('/gather/stage', sessionAuth, 'spssController.gatherStage');
     app.post('/gather/stage/load', sessionAuth, 'spssController.loadGatherStage');
+    app.get('/tools/check-tz', sessionAuth, 'spssController.checkTz');
+    app.post('/tools/load', sessionAuth, 'spssController.loadBaseData');
 
     // wap页面
     app.get('/wap', 'wapController.index');

+ 3 - 3
app/service/change_audit.js

@@ -206,9 +206,9 @@ module.exports = app => {
          * @return {object} 返回结果
          */
         async getListGroupByTimes(cid, times) {
-            const sql = 'SELECT * FROM ?? WHERE ' +
-                'cid = ? AND times = ? GROUP BY usite';
-            const sqlParam = [this.tableName, cid, times];
+            const sql = 'SELECT * FROM ?? where id in (SELECT MAX(id) FROM ?? WHERE ' +
+                'cid = ? AND times = ? GROUP BY usite)';
+            const sqlParam = [this.tableName, this.tableName, cid, times];
             const list = await this.db.query(sql, sqlParam);
             return list;
         }

+ 58 - 0
app/view/spss/check_tz.ejs

@@ -0,0 +1,58 @@
+<% include ./sub_menu.ejs %>
+<div class="panel-content">
+    <div class="panel-title">
+        <div class="title-main d-flex">
+            <% include ./sub_mini_menu.ejs %>
+            <div>
+                <div class="d-inline-block">
+                    <div class="dropdown">
+                        <button class="btn btn-sm btn-light dropdown-toggle text-primary" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                            <i class="fa fa-list-ol"></i> 显示层级
+                        </button>
+                        <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                            <a class="dropdown-item" name="showLevel" tag="1" href="javascirpt: void(0);">第一层</a>
+                            <a class="dropdown-item" name="showLevel" tag="2" href="javascirpt: void(0);">第二层</a>
+                            <a class="dropdown-item" name="showLevel" tag="3" href="javascirpt: void(0);">第三层</a>
+                            <a class="dropdown-item" name="showLevel" tag="4" href="javascirpt: void(0);">第四层</a>
+                            <a class="dropdown-item" name="showLevel" tag="5" href="javascirpt: void(0);">第五层</a>
+                            <a class="dropdown-item" name="showLevel" tag="last" href="javascirpt: void(0);">最底层</a>
+                            <a class="dropdown-item" name="showLevel" tag="leafXmj" href="javascirpt: void(0);">只显示项目节</a>
+                        </div>
+                    </div>
+                </div>
+                <div class="d-inline-block">
+                    <input class="form-control form-control-sm"  placeholder="输入要检查的标段的ID" type="text" name="tz-id">
+                </div>
+                <div class="d-inline-block">
+                    <button href="javascript: void(0)" id="load-tz" class="btn btn-sm btn-light text-primary">
+                        加载
+                    </button>
+                </div>
+            </div>
+            <div class="ml-auto"></div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-header p-0"></div>
+        <div class="c-body">
+            <div class="sjs-height-1" id="bills-spread">
+            </div>
+            <div class="bcontent-wrap" id="main-bottom">
+                <div id="main-resize" class="resize-y"  r-Type="height" div1="#bills-spread" div2="#main-bottom" store-id="compare-main" store-version="1.0.0" min="100"></div>
+                <div class="bc-bar mb-1">
+                    <ul class="nav nav-tabs">
+                        <li class="nav-item">
+                            <a class="nav-link active" data-toggle="tab" href="#xmujie" role="tab">计量单元</a>
+                        </li>
+                    </ul>
+                </div>
+                <div class="tab-content">
+                    <div class="tab-pane active" id="xmujie">
+                        <div class="sp-wrap" id="pos-spread">
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>

+ 8 - 0
app/view/spss/sub_menu_list.ejs

@@ -19,4 +19,12 @@
             <a href="/gather/stage"><span class="ml-3">期计量汇总</span></a>
         </li>
     </ul>
+</div>
+<div class="nav-box">
+    <h3><i class="fa fa-list-alt"></i> 其他工具</h3>
+    <ul class="nav-list list-unstyled">
+        <li class="<% if (ctx.url === '/tools/check-tz') { %>active<% } %>">
+            <a href="/tools/check-tz"><span class="ml-3">检测台账</span></a>
+        </li>
+    </ul>
 </div>

+ 1 - 0
app/view/wap/shenpi_change.ejs

@@ -275,6 +275,7 @@
                         <div class="custom-control custom-radio custom-control-inline">
                             <input class="custom-control-input" type="radio" name="status" id="change-backnew" value="<%- auditConst.auditStatus.backnew %>" checked>
                             <label class="custom-control-label" for="change-backnew">退回上一审批人 <%- auditGroupList[checkingAudit.usite-1].name %></label>
+                            <input type="hidden" name="audit_last_id" value="<%= auditGroupList[checkingAudit.usite-1].id %>">
                         </div>
                     <% } %>
                 </div>

+ 18 - 0
config/web.js

@@ -589,6 +589,24 @@ const JsFiles = {
                 mergeFile: 'gather_stage',
             },
         },
+        tools: {
+            checkTz: {
+                files: [
+                    "/public/js/spreadjs/sheets/v11/gc.spread.sheets.all.11.2.2.min.js",
+                    "/public/js/decimal.min.js",
+                ],
+                mergeFiles: [
+                    "/public/js/sub_menu.js",
+                    "/public/js/div_resizer.js",
+                    "/public/js/spreadjs_rela/spreadjs_zh.js",
+                    "/public/js/shares/sjs_setting.js",
+                    "/public/js/zh_calc.js",
+                    "/public/js/path_tree.js",
+                    "/public/js/spss_check_tz.js",
+                ],
+                mergeFile: 'spss_check_tz',
+            }
+        },
         report: {
             main: {
                 files: [