Explorar o código

Merge branch 'master' of http://192.168.1.12:3000/caiaolin/Calculation

laiguoran %!s(int64=6) %!d(string=hai) anos
pai
achega
cd77417191

+ 1 - 1
app/const/tender_info.js

@@ -59,7 +59,7 @@ const defaultInfo = {
     decimal: {
         up: 2,
         qty: 3,
-        tp: 2,
+        tp: 0,
         pay: false,
         payTp: 0,
     },

+ 2 - 1
app/controller/ledger_controller.js

@@ -67,9 +67,10 @@ module.exports = app => {
                 col.formatter = formatter;
             }
             const tpFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.tp);
-            const upFormatter = this.ctx.helper.getNumberFormatter(2);
+            const upFormatter = this.ctx.helper.getNumberFormatter(this.ctx.tender.info.decimal.up);
             const ledger = JSON.parse(JSON.stringify(spreadConst.ledgerSpread));
             setColFormat(ledger.cols, 'unit_price', upFormatter);
+            setColFormat(ledger.cols, 'dgn_price', upFormatter);
             setColFormat(ledger.cols, 'total_price', tpFormatter);
             setColFormat(ledger.cols, 'deal_tp', tpFormatter);
             const pos = JSON.parse(JSON.stringify(spreadConst.ledgerPosSpread));

+ 29 - 15
app/controller/stage_controller.js

@@ -13,6 +13,7 @@ const auditConst = require('../const/audit').stage;
 const spreadConst = require('../const/spread');
 const tenderConst = require('../const/tender');
 const payConst = require('../const/deal_pay.js');
+const changeConst = require('../const/change');
 const measureType = tenderConst.measureType;
 const path = require('path');
 const PayCalculator = require('../lib/pay_calc');
@@ -133,6 +134,7 @@ module.exports = app => {
                 await this._getStage(ctx);
                 const renderData = this._getDefaultRenderData(ctx);
                 [renderData.ledgerSpread, renderData.posSpread] = this._getSpreadSetting();
+                renderData.changeConst = changeConst;
                 renderData.ledgerData = await ctx.service.ledger.getDataByTenderId(ctx.tender.id, -1);
                 renderData.curStageData = await ctx.service.stageBills.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.times, 0);
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.stage.index);
@@ -158,7 +160,7 @@ module.exports = app => {
         }
 
         /**
-         * 获取期数据(截止上期 & 本期)
+         * 获取期数据(截止上期 & 本期) (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -181,7 +183,7 @@ module.exports = app => {
         }
 
         /**
-         * 保存数据
+         * 保存数据 (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -213,7 +215,7 @@ module.exports = app => {
         }
 
         /**
-         * 中间计量
+         * 中间计量 (Get)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -231,7 +233,7 @@ module.exports = app => {
         }
 
         /**
-         * 设置中间计量生成规则,并生成中间计量数据
+         * 设置中间计量生成规则,并生成中间计量数据 (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -256,7 +258,7 @@ module.exports = app => {
         }
 
         /**
-         * 加载数据
+         * 加载数据 (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -289,7 +291,7 @@ module.exports = app => {
         }
 
         /**
-         * 中间计量,生成规则,高级设置
+         * 中间计量,生成规则,高级设置 (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -314,7 +316,7 @@ module.exports = app => {
         }
 
         /**
-         * 中间计量,编辑中间计量数据
+         * 中间计量,编辑中间计量数据(Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -342,7 +344,7 @@ module.exports = app => {
         }
 
         /**
-         * 中间计量,添加草图,上传图片
+         * 中间计量,添加草图,上传图片 (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -361,7 +363,7 @@ module.exports = app => {
         }
 
         /**
-         * 中间计量,设置草图
+         * 中间计量,设置草图 (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -406,7 +408,7 @@ module.exports = app => {
         }
 
         /**
-         * 合同支付
+         * 合同支付 (Get)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -436,7 +438,7 @@ module.exports = app => {
         }
 
         /**
-         * 合同支付 - 编辑合同支付项
+         * 合同支付 - 编辑合同支付项 (Ajax)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -498,7 +500,7 @@ module.exports = app => {
         }
 
         /**
-         * 合同支付 - 章节明细
+         * 合同支付 - 章节明细 (Ajax-Post)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -563,7 +565,7 @@ module.exports = app => {
         }
 
         /**
-         * 变更令
+         * 变更令 (Get)
          * @param ctx
          * @returns {Promise<void>}
          */
@@ -579,12 +581,24 @@ module.exports = app => {
         }
 
         /**
-         * 查询可用变更令
+         * 查询可用变更令 (Ajax-Post)
          * @param ctx
          * @returns {Promise<void>}
          */
         async searchValidChange(ctx) {
-
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.bills && !data.pos) {
+                    throw '数据错误';
+                }
+                const bills = data.bills ? data.bills : await ctx.service.ledger.getDataById(data.pos.lid);
+                const pos = data.pos;
+                const changes = await ctx.service.change.getValidChanges(bills, pos);
+                ctx.body = {err: 0, msg: '', data: changes};
+            } catch(err) {
+                this.log(err);
+                ctx.body = {err: 1, msg: err.toString(), data: null};
+            }
         }
 
         // 审批相关

+ 1 - 1
app/controller/tender_controller.js

@@ -209,7 +209,7 @@ module.exports = app => {
                     throw '提交数据错误';
                 }
                 await ctx.service.tenderInfo.saveTenderInfo(ctx.tender.id, data);
-                ctx.body = { err: 0, msg: '', data };
+                ctx.body = { err: 0, msg: '', data: JSON.parse(ctx.request.body.data) };
             } catch (err) {
                 this.log(err);
                 ctx.body = { err: 1, msg: err.toString(), data: null };

+ 12 - 2
app/public/js/ledger.js

@@ -685,8 +685,18 @@ $(document).ready(function() {
                     data.updateData[col.field] = col.type === 'Number' ? parseFloat(newText) : newText;
                 }
                 postData('/tender/' + getTenderId() + '/pos/update', data, function (result) {
-                    pos.updateDatas(result.pos);
-                    SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    const updateRst = pos.updateDatas(result.pos);
+                    // 刷新当前行, 不适用于新增(在非下一空白行新增)
+                    if (updateRst.create.length > 0) {
+                        // info.sheet.addRows(info.row, 1);
+                        // if (info.sheet.zh_data.length === 0) {
+                        //     info.sheet.zh_data = pos.ledgerPos[itemsPre + node.id] || [];
+                        // }
+                        // SpreadJsObj.reLoadRowData(info.sheet, info.sheet.zh_data.length - 1);
+                        posOperationObj.loadCurPosData();
+                    } else {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    }
                     ledgerTree.loadPostData(result.ledger, function (loadResult) {
                         treeOperationObj.refreshTree(ledgerSpread.getActiveSheet(), loadResult);
                     });

+ 8 - 3
app/public/js/path_tree.js

@@ -47,6 +47,7 @@ class PosData {
      */
     updateDatas(data) {
         const datas = data instanceof Array ? data : [data];
+        const result = { create: [], update: [] };
         for (const d of datas) {
             const key = itemsPre + d[this.setting.id];
             if (!this.items[key]) {
@@ -58,13 +59,16 @@ class PosData {
                     this.ledgerPos[masterKey] = [];
                 }
                 this.ledgerPos[masterKey].push(d);
+                result.create.push(d);
             } else {
                 const pos = this.items[key];
                 for (const prop in d) {
                     pos[prop] = d[prop];
                 }
+                result.update.push(pos);
             }
         }
+        return result;
     }
 
     /**
@@ -281,7 +285,8 @@ const createNewPathTree = function (type, setting) {
             }
             this.sortTreeNode();
             for (const node of this.nodes) {
-                node.expanded = node.children.length > 0;
+                //node.expanded = node.children.length > 0;
+                node.expanded = true;
                 node.visible = true;
             }
         }
@@ -574,7 +579,7 @@ const createNewPathTree = function (type, setting) {
             loadedData = _.uniq(loadedData);
             for (const node of loadedData) {
                 node.children = this.getChildren(node);
-                node.expanded = node.children.length > 0 && node.children[0].visible;
+                node.expanded = node.children.length === 0 ? true : node.children[0].visible;
             }
             this.sortTreeNode(true);
             return loadedData;
@@ -606,7 +611,7 @@ const createNewPathTree = function (type, setting) {
                     const node = JSON.parse(JSON.stringify(data));
                     this.items[keyName] = node;
                     this.datas.push(node);
-                    node.expanded = false;
+                    node.expanded = true;
                     node.visible = true;
                     loadedData.push(node);
                     if (resortData.indexOf(node) === -1) {

+ 42 - 17
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -374,18 +374,20 @@ const SpreadJsObj = {
         const sortData = sheet.zh_dataType === 'tree' ? sheet.zh_tree.nodes : sheet.zh_data;
         this.beginMassOperation(sheet);
         try {
-            sheet.clear(0, 0, sheet.getRowCount(), sheet.getColumnCount(), spreadNS.SheetArea.viewport, spreadNS.StorageType.data)
+            sheet.clear(0, 0, sheet.getRowCount(), sheet.getColumnCount(), spreadNS.SheetArea.viewport, spreadNS.StorageType.data);
             // 设置总行数
             const totalRow = sortData.length + sheet.zh_setting.emptyRows;
             sheet.setRowCount(totalRow, spreadNS.SheetArea.viewport);
             // 控制空白行
             const emptyRows = sheet.getRange(sortData.length, -1, sheet.zh_setting.emptyRows, -1);
             emptyRows.locked(sheet.zh_dataType === 'tree');
-            // 单元格写入数据
-            sortData.forEach(function (data, i) {
-                self._loadRowData(sheet, data, i);
-                sheet.setRowVisible(i, data.visible);
-            });
+            if (sortData) {
+                // 单元格写入数据
+                sortData.forEach(function (data, i) {
+                    self._loadRowData(sheet, data, i);
+                    sheet.setRowVisible(i, data.visible);
+                });
+            }
             // 设置列单元格格式
             sheet.zh_setting.cols.forEach(function (col, j) {
                 //if (!col.cellType) { return; }
@@ -604,16 +606,25 @@ const SpreadJsObj = {
      */
     refreshTreeRowVisible: function (sheet) {
         this.beginMassOperation(sheet);
-        if (sheet.zh_tree) {
-            for (const iRow in sheet.zh_tree.nodes) {
-                const node = sheet.zh_tree.nodes[iRow];
-                if (node.visible !== undefined && node.visible !== null) {
-                    sheet.setRowVisible(iRow, node.visible);
-                } else {
-                    sheet.setRowVisible(iRow, true);
-                }
+        const sortData = sheet.zh_dataType === this.DataType.Data ? sheet.zh_data : sheet.zh_tree.nodes;
+        for (const iRow in sortData) {
+            const node = sortData[iRow];
+            if (node.visible !== undefined && node.visible !== null) {
+                sheet.setRowVisible(iRow, node.visible);
+            } else {
+                sheet.setRowVisible(iRow, true);
             }
         }
+        // if (sheet.zh_tree) {
+        //     for (const iRow in sheet.zh_tree.nodes) {
+        //         const node = sheet.zh_tree.nodes[iRow];
+        //         if (node.visible !== undefined && node.visible !== null) {
+        //             sheet.setRowVisible(iRow, node.visible);
+        //         } else {
+        //             sheet.setRowVisible(iRow, true);
+        //         }
+        //     }
+        // }
         this.endMassOperation(sheet);
     },
     /**
@@ -1095,8 +1106,16 @@ const SpreadJsObj = {
 
             };
             proto.paint = function (canvas, value, x, y, w, h, style, options) {
-                const img = this.getImage(options.sheet, options.row, options.col);
                 const col = options.sheet.zh_setting.cols[options.col];
+
+                const sortData = SpreadJsObj.getSortData(options.sheet);
+                const data = sortData ? sortData[options.row] : null;
+                let showImage = true;
+                if (col.showImage && Object.prototype.toString.apply(col.showImage) === "[object Function]") {
+                    showImage = col.showImage(data);
+                }
+                const img = showImage ? this.getImage(options.sheet, options.row, options.col) : null;
+
                 const indent = col.indent ? col.indent : 10;
                 if (style.hAlign === spreadNS.HorizontalAlign.right) {
                     if (img) {
@@ -1183,10 +1202,16 @@ const SpreadJsObj = {
                 }
             };
             proto.processMouseUp = function (hitinfo) {
+                const col = hitinfo.sheet.zh_setting.cols[hitinfo.col];
+                const sortData = SpreadJsObj.getSortData(hitinfo.sheet);
+                const data = sortData ? sortData[hitinfo.row] : null;
+                if (col.showImage && Object.prototype.toString.apply(col.showImage) === "[object Function]") {
+                    if (!col.showImage(data)) {
+                        return;
+                    }
+                }
                 const imageClick = hitinfo.sheet.zh_setting ? hitinfo.sheet.zh_setting.imageClick : null;
                 if (imageClick && Object.prototype.toString.apply(imageClick) === "[object Function]") {
-                    const sortData = SpreadJsObj.getSortData(hitinfo.sheet);
-                    const data = sortData ? sortData[hitinfo.row] : null;
                     imageClick(data);
                     const cell = hitinfo.sheet.getCell(hitinfo.row, hitinfo.col);
                     cell.tag(null);

+ 200 - 25
app/public/js/stage.js

@@ -47,25 +47,46 @@ function customizeStageTreeSetting(setting, customDisplay) {
         }
     }
 }
+/**
+ * 初始化 树结构 列事件
+ * @param setting
+ */
+function initTreeColSettingEvents(setting) {
+    const Events = {
+        readOnly: {
+            measureData: function (node) {
+                return node.children && node.children.length > 0;
+            },
+        },
+    };
+    const getEvent = function (eventName) {
+        const names = eventName.split('.');
+        let event = Events;
+        for (let name of names) {
+            if (event[name]) {
+                event = event[name];
+            } else {
+                return null;
+            }
+        }
+        if (event && Object.prototype.toString.apply(event) !== "[object Function]") {
+            return null;
+        } else {
+            return event;
+        }
+    };
+
+    for (const col of setting.cols) {
+        if (col.readOnly && Object.prototype.toString.apply(col.readOnly) === "[object String]") {
+            col.readOnly = getEvent(col.readOnly);
+        }
+    }
+}
 
 $(document).ready(() => {
+    // 界面布局
     autoFlashHeight();
-    // 初始化 台账 spread
-    const slSpread = SpreadJsObj.createNewSpread($('#stage-ledger')[0]);
-    customizeStageTreeSetting(ledgerSpreadSetting, customColDisplay());
-    // 数量变更列,添加按钮
-    const col = _.find(ledgerSpreadSetting.cols, {field: 'qc_qty'});
-    col.readOnly = true;
-    col.cellType = 'imageBtn';
-    col.hoverImg = '#ellipsis-icon';
-    col.indent = 5;
-    ledgerSpreadSetting.imageClick = function (data) {
-        postData(window.location.pathname + 'valid-change', data, function (result) {
-            $('#use-bg').modal('show');
-        });
-    };
-    //
-    SpreadJsObj.initSheet(slSpread.getActiveSheet(), ledgerSpreadSetting);
+    // 初始化 台账树结构 数据结构
     const stageTreeSetting = {
         id: 'ledger_id',
         pid: 'ledger_pid',
@@ -95,16 +116,8 @@ $(document).ready(() => {
             node.dgn_price = null;
         }
     };
-    // 初始化 台账树结构
     const stageTree = createNewPathTree('stage', stageTreeSetting);
-    stageTree.loadDatas(ledgerData);
-    stageTree.loadCurStageData(curStageData);
-    // 根据设置 计算 台账树结构
-    treeCalc.calculateAll(stageTree);
-    // 绘制界面
-    SpreadJsObj.loadSheetData(slSpread.getActiveSheet(), 'tree', stageTree);
-
-    // 初始化 部位明细
+    // 初始化 部位明细 数据结构
     const stagePosSetting = {
         id: 'id', ledgerId: 'lid',
         updateFields: ['contract_qty', 'qc_qty', 'postil'],
@@ -116,7 +129,169 @@ $(document).ready(() => {
         pos.end_gather_qty = _.add(pos.pre_gather_qty, pos.gather_qty);
     };
     const stagePos = new StagePosData(stagePosSetting);
+
+    class Changes {
+        constructor(obj) {
+            const self = this;
+            this.obj = obj;
+            // 初始化 清单编号窗口 参数
+            this.spreadSetting = {
+                cols: [
+                    {title: '已用', field: 'used', width: 45, formatter: '@', cellType: 'checkbox', readOnly: true, hAlign: 1,},
+                    {title: '变更令号', field: 'code', width: 100, formatter: '@', readOnly: true},
+                    {title: '名称', field: 'name', width: 120, formatter: '@', readOnly: true},
+                    {title: '总数量', field: 'amount', width: 60, formatter: '@', readOnly: true},
+                    {title: '可变更数量', field: 'vamount', width: 60, readOnly: true},
+                    {title: '本期计量', field: 'uamount', width: 60, formatter: '@'},
+                ],
+                emptyRows: 0,
+                headRows: 1,
+                headRowHeight: [40],
+            };
+            this.curChangeId = '';
+            this.spread = SpreadJsObj.createNewSpread($('#change-spread')[0]);
+            this.firstView = true;
+            SpreadJsObj.initSheet(this.spread.getActiveSheet(), this.spreadSetting);
+            // 初次显示,需刷新spread界面,保证界面绘制正确
+            this.obj.bind('shown.bs.modal', function () {
+                if (self.firstView) {
+                    self.firstView = false;
+                    self.spread.refresh();
+                }
+            });
+            // 切换变更令,加载右侧明细数据
+            this.spread.bind(spreadNS.Events.SelectionChanged, function (e, info) {
+                const change = SpreadJsObj.getSelectObject(info.sheet);
+                self._loadChangeDetail(change);
+            });
+            // 过滤可变更数量为0
+            $('#customCheckDisabled').click(function () {
+                self._filterEmptyChange(!this.checked);
+            })
+        }
+        _loadChangeDetail(change) {
+            if (change) {
+                if (change.cid === this.curChangeId) { return; }
+
+                this.curChangeId = change.cid;
+                const inputs = $('input[type!=checkbox]', this.obj);
+                for (const i of inputs) {
+                    const field = $(i).attr('name');
+                    const text = (field && change[field]) ? change[field] : '';
+                    $(i).val(text);
+                }
+                const textareas = $('textarea', this.obj);
+                for (const ta of textareas) {
+                    const field = $(ta).attr('name');
+                    const text = (field && change[field]) ? change[field] : '';
+                    ta.innerText = text;
+                }
+                const html = [];
+                for (const a of change.attachments) {
+                    html.push('<tr>');
+                    html.push('<td>', a.filename + a.fileext, '</td>');
+                    html.push('<td>', a.u_name, '</td>');
+                    html.push('</tr>');
+                }
+                // 变更类型
+                const cType = change.type.split(',');
+                $('input[name="type"]').prop("checked", false);
+                for (const c of cType) {
+                    $('input[name="type"][value='+ c +']').prop("checked", true);
+                }
+                // 变更类别
+                $('select[name=class]').val(change.class);
+                // 变更性质
+                $('select[name=quality]').val(change.quality);
+                // 变更单位
+                $('select[name=company]').html('<option>' + change.company + '</option>');
+                // 费用承担方
+                $('input[name=charge][value=' + change.charge + ']').prop('checked', true);
+                // 附件
+                $('#attachment').html(html.join(''));
+            } else {
+                const inputs = $('input', this.obj);
+                for (const i of inputs) {
+                    $(i).val('');
+                }
+                const textareas = $('textarea', this.obj);
+                for (const ta of textareas) {
+                    ta.innerText = '';
+                }
+                $('#attachment').html('');
+            }
+        }
+        _viewChanges() {
+            const sheet = this.spread.getActiveSheet();
+            if (this.changes) {
+                SpreadJsObj.loadSheetData(sheet, SpreadJsObj.DataType.Data, this.changes);
+                sheet.setSelection(0, 0, 1, 1);
+                this._loadChangeDetail(this.changes[0]);
+                this._filterEmptyChange(!$('#customCheckDisabled')[0].checked);
+            } else {
+                toast('查询变更令有误,请刷新页面后重试', 'warning');
+            }
+        }
+        _filterEmptyChange(isFilter) {
+            for (const c of this.changes) {
+                c.visible = isFilter ? (c.vamount || c.vamount === 0) : true;
+            }
+            SpreadJsObj.refreshTreeRowVisible(this.spread.getActiveSheet());
+        }
+        loadChanges(data) {
+            this.callData = data;
+            const self = this;
+            postData(window.location.pathname + '/valid-change', data, function (result) {
+                self.changes = result;
+                self._viewChanges();
+                self.obj.modal('show');
+            });
+        }
+    }
+    const changesObj = new Changes($('#use-bg'));
+
+    // 初始化 台账 spread
+    const slSpread = SpreadJsObj.createNewSpread($('#stage-ledger')[0]);
+    customizeStageTreeSetting(ledgerSpreadSetting, customColDisplay());
+    // 数量变更列,添加按钮
+    const col = _.find(ledgerSpreadSetting.cols, {field: 'qc_qty'});
+    col.readOnly = true;
+    col.cellType = 'imageBtn';
+    col.hoverImg = '#ellipsis-icon';
+    col.indent = 5;
+    col.showImage = function (data) {
+        if (!data || (data.children && data.children.length > 0)) {
+            return false;
+        } else {
+            const nodePos = stagePos.getLedgerPos(data.id);
+            return !(nodePos && nodePos.length > 0);
+        }
+    };
+    ledgerSpreadSetting.imageClick = function (data) {
+        changesObj.loadChanges({bills: data});
+    };
+    //
+    SpreadJsObj.initSheet(slSpread.getActiveSheet(), ledgerSpreadSetting);
+    stageTree.loadDatas(ledgerData);
+    stageTree.loadCurStageData(curStageData);
+    // 根据设置 计算 台账树结构
+    treeCalc.calculateAll(stageTree);
+    // 绘制界面
+    SpreadJsObj.loadSheetData(slSpread.getActiveSheet(), 'tree', stageTree);
+
+    // 初始化 部位明细 Spread
     const spSpread = SpreadJsObj.createNewSpread($('#stage-pos')[0]);
+    const spCol = _.find(posSpreadSetting.cols, {field: 'qc_qty'});
+    spCol.readOnly = true;
+    spCol.cellType = 'imageBtn';
+    spCol.hoverImg = '#ellipsis-icon';
+    spCol.indent = 5;
+    spCol.showImage = function (data) {
+        return data;
+    };
+    posSpreadSetting.imageClick = function (data) {
+        changesObj.loadChanges({pos: data});
+    };
     SpreadJsObj.initSheet(spSpread.getActiveSheet(), posSpreadSetting);
 
     const stageTreeSpreadObj = {

+ 40 - 0
app/service/change.js

@@ -671,6 +671,46 @@ module.exports = app => {
             }
             return result;
         }
+
+        /**
+         * 查询可用的变更令
+         * @param bills - 查询的清单
+         * @param pos - 查询的部位
+         * @returns {Promise<*>} - 可用的变更令列表
+         */
+        async getValidChanges(bills, pos) {
+            const filter = 'cb.`code` = ' + this.db.escape(bills.b_code) + (pos ? ' And cb.`detail` = ' + this.db.escape(pos.name) : '');
+            const sql = 'SELECT c.cid, c.code, c.name, c.w_code, c.p_code, c.peg, c.org_name, c.org_code, c.new_name, c.new_code,' +
+                        '    c.content, c.basis, c.memo, c.type, c.class, c.quality, c.company, c.charge, ' +
+                        '    cb.code As b_code, cb.name As b_name, cb.unit As b_unit, cb.samount As b_amount, cb.detail As b_detail ' +
+                        '  FROM ?? As c ' +
+                        '  Left Join ?? As cb ' +
+                        '  On c.cid = cb.cid ' +
+                        '  WHERE c.status = ? And ' + filter;
+            const sqlParam = [this.tableName, this.ctx.service.changeAuditList.tableName, audit.flow.status.checked];
+            const changes = await this.db.query(sql, sqlParam);
+            for (const c of changes) {
+                const aSql = 'SELECT ca.*, pa.name As u_name, pa.role As u_role ' +
+                             '  FROM ?? As ca ' +
+                             '  Left Join ?? As pa ' +
+                             '  On ca.uid = pa.id ' +
+                             '  Where ca.cid = ?';
+                const aSqlParam = [this.ctx.service.changeAtt.tableName, this.ctx.service.projectAccount.tableName, c.cid];
+                c.attachments = await this.db.query(aSql, aSqlParam);
+            }
+            // const sql = 'SELECT c.* FROM ?? As c' +
+            //     '  WHERE c.`cid` in (' +
+            //     '    SELECT cb.`cid` FROM ?? As cb' +
+            //     '      WHERE ' + filter +
+            //     '      GROUP BY cb.`cid`) ' +
+            //     '    And c.status = ?';
+            // const sqlParam = [this.tableName, this.ctx.service.changeAuditList.tableName, audit.flow.status.checked];
+            // const changes = await this.db.query(sql, sqlParam);
+            // for (const c of changes) {
+            //     c.bills = await this.ctx.service.changeAuditList.getDataByCondition({cid: c.cid, code: bills.b_code});
+            // }
+            return changes;
+        }
     }
     return Change;
 };

+ 19 - 1
app/service/ledger.js

@@ -22,7 +22,7 @@ const keyFields = {
 };
 // 以下字段仅可通过树结构操作改变,不可直接通过update方式从接口提交,发现时过滤
 const readOnlyFields = ['id', 'tender_id', 'ledger_id', 'ledger_pid', 'order', 'level', 'full_path', 'is_leaf'];
-const calcFields = ['quantity', 'unit_price', 'total_price', 'deal_qty', 'deal_tp'];
+const calcFields = ['quantity', 'unit_price', 'total_price', 'deal_qty', 'deal_tp', 'dgn_qty1', 'dgn_qty2'];
 const upFields = ['unit_price'];
 const qtyFields = ['quantity', 'deal_qty', 'dgn_qty1', 'dgn_qty2'];
 const tpFields = ['total_price', 'deal_tp'];
@@ -830,10 +830,12 @@ module.exports = app => {
          * @return {Promise<void>}
          */
         async addStdNodeWithParent(tenderId, stdData, stdLib) {
+            // 查询完整标准清单,并按层次排序
             const fullLevel = await stdLib.getFullLevelDataByFullPath(stdData.list_id, stdData.full_path);
             fullLevel.sort(function(x, y) {
                 return x.level - y.level;
             });
+
             let isNew = false,
                 node,
                 firstNew,
@@ -842,6 +844,7 @@ module.exports = app => {
             const expandIds = [];
             this.transaction = await this.db.beginTransaction();
             try {
+                // 从最顶层节点依次查询是否存在,否则添加
                 for (let i = 0, len = fullLevel.length; i < len; i++) {
                     const stdNode = fullLevel[i];
 
@@ -1091,6 +1094,10 @@ module.exports = app => {
                     value: Math.abs(orderInc),
                     selfOperate: orderInc > 0 ? '+' : '-',
                 });
+                this.sqlBuilder.setAndWhere('tender_id', {
+                    value: selectData.tender_id,
+                    operate: '=',
+                });
                 this.sqlBuilder.setAndWhere('ledger_pid', {
                     value: selectData.ledger_pid,
                     operate: '=',
@@ -1332,6 +1339,16 @@ module.exports = app => {
             return bChanged ? result : undefined;
         }
 
+        _checkField(data, field) {
+            const fields = field instanceof Array ? field : [field];
+            for (const prop in data) {
+                if (fields.indexOf(prop) >= 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
         /**
          * 检查data中是否含有计算字段
          * @param {Object} data
@@ -1630,6 +1647,7 @@ module.exports = app => {
                         }
                         updateData = this._filterUpdateInvalidField(updateNode.id, calcData);
                     } else {
+
                         updateData = this._filterUpdateInvalidField(updateNode.id, row);
                     }
                     await this.transaction.update(this.tableName, updateData);

+ 41 - 46
app/view/stage/modal.ejs

@@ -50,13 +50,7 @@
                                 </div>
                             </li>
                         </ul>
-                        <div class="modal-height-500">
-                            <table class="table table-bordered">
-                                <tr><th>已用</th><th>变更令号</th><th>名称</th><th>总数量</th><th>可变更数量</th><th>本期计量</th></tr>
-                                <tr><td><i class="fa fa-check text-success"></i></td><td>CW01-BG-1</td><td>增加清淤换填数量</td><td>100</td><td>50</td><td>20</td></tr>
-                                <tr><td><i class="fa fa-check text-success"></i></td><td>CW01-BG-2</td><td>增加挖淤及回填数量</td><td>150</td><td>120</td><td>100</td></tr>
-                                <tr><td></td><td>CW01-BG-3</td><td>增加清淤换填数量</td><td>150</td><td>100</td><td></td></tr>
-                            </table>
+                        <div class="modal-height-500" id="change-spread">
                         </div>
                     </div>
                     <div class="col-5">
@@ -68,7 +62,7 @@
                                 <a class="nav-link" data-toggle="tab" href="#detail" role="tab">更多变更信息</a>
                             </li>
                             <li class="nav-item">
-                                <a class="nav-link" data-toggle="tab" href="#fujian" role="tab">附件</a>
+                                <a class="nav-link" data-toggle="tab" href="#bg-fujian" role="tab">附件</a>
                             </li>
                         </ul>
                         <div class="modal-height-500" style="overflow: auto">
@@ -76,104 +70,105 @@
                                 <div id="bgsm" class="tab-pane active">
                                     <div class="form-group">
                                         <label></label>
-                                        <textarea class="form-control form-control-sm" rows="6" readonly>由于K0+532涵洞基底土质天然含水率为25%、收费站出口右侧加宽段K0+120-K0+190段基底土质天然含水率为28.8%。含水率较大形成过湿土,地基松软,无法满足承载力要求。经处项目办、设计、监理、施工单位四方勘察,采用抛石挤淤、砂砾换填以达到地基承载力。
-                                  </textarea>
+                                        <textarea name="content" class="form-control form-control-sm" rows="6" readonly>
+                                        </textarea>
                                     </div>
                                 </div>
                                 <div id="detail" class="tab-pane">
                                     <div class="form-group mt-3">
                                         <label>批复编号</label>
-                                        <input class="form-control form-control-sm" value="LZTJ-1标项目部发变更(2015)001号" type="text" readonly>
+                                        <input class="form-control form-control-sm" name="p_code" value="LZTJ-1标项目部发变更(2015)001号" type="text" readonly>
                                     </div>
                                     <div class="form-group">
                                         <label>工程名称</label>
-                                        <input class="form-control form-control-sm" value="收费站出口右侧加宽段及K0+532基底换填" type="text" readonly>
+                                        <input class="form-control form-control-sm" name="name" value="收费站出口右侧加宽段及K0+532基底换填" type="text" readonly>
                                     </div>
                                     <div class="form-group">
                                         <label>桩号</label>
-                                        <input class="form-control form-control-sm" value="K0+532" type="text" readonly>
+                                        <input class="form-control form-control-sm" name="peg" value="K0+532" type="text" readonly>
                                     </div>
                                     <div class="form-group">
                                         <label>原设计图名称</label>
-                                        <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        <input class="form-control form-control-sm" name="org_name" placeholder="" type="text" readonly>
                                     </div>
                                     <div class="form-group">
                                         <label>原图号</label>
-                                        <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        <input class="form-control form-control-sm" name="org_code" placeholder="" type="text" readonly>
                                     </div>
                                     <div class="form-group">
                                         <label>变更设计图名称</label>
-                                        <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        <input class="form-control form-control-sm" name="new_name" placeholder="" type="text" readonly>
                                     </div>
                                     <div class="form-group">
                                         <label>变更图号</label>
-                                        <input class="form-control form-control-sm" placeholder="" type="text" readonly>
+                                        <input class="form-control form-control-sm" name="new_code" placeholder="" type="text" readonly>
                                     </div>
                                     <div class="form-group">
                                         <label>工程变更理由及内容</label>
-                                        <textarea class="form-control form-control-sm" rows="6" readonly>由于K0+532涵洞基底土质天然含水率为25%、收费站出口右侧加宽段K0+120-K0+190段基底土质天然含水率为28.8%。含水率较大形成过湿土,地基松软,无法满足承载力要求。经处项目办、设计、监理、施工单位四方勘察,采用抛石挤淤、砂砾换填以达到地基承载力。
+                                        <textarea class="form-control form-control-sm" name="content" rows="6" readonly>由于K0+532涵洞基底土质天然含水率为25%、收费站出口右侧加宽段K0+120-K0+190段基底土质天然含水率为28.8%。含水率较大形成过湿土,地基松软,无法满足承载力要求。经处项目办、设计、监理、施工单位四方勘察,采用抛石挤淤、砂砾换填以达到地基承载力。
                                     </textarea>
                                     </div>
                                     <div class="form-group">
                                         <label>工程变更合同依据</label>
-                                        <textarea class="form-control form-control-sm" rows="6" readonly></textarea>
+                                        <textarea class="form-control form-control-sm" name="basis" rows="6" readonly></textarea>
                                     </div>
                                     <div class="form-group">
                                         <label>变更类型</label>
                                         <div class="checkbox">
+                                            <% for (const t in changeConst.type) { %>
+                                            <% const cType = changeConst.type[t] %>
                                             <label class="checkbox-inline">
-                                                <input id="inlineCheckbox1" value="option1" checked="" type="checkbox" disabled>A.位置
+                                                <input value="<%- cType.value %>" name="type" type="checkbox" disabled><%- cType.name %>
                                             </label>
-                                            <!-- <label class="checkbox-inline">
-                                              <input id="inlineCheckbox2" value="option2" type="checkbox">B.数量
-                                            </label>
-                                            <label class="checkbox-inline">
-                                              <input id="inlineCheckbox3" value="option3" type="checkbox">C.结构
-                                            </label>
-                                            <label class="checkbox-inline">
-                                              <input id="inlineCheckbox3" value="option3" checked="" type="checkbox">D.新增
-                                            </label>
-                                            <label class="checkbox-inline">
-                                              <input id="inlineCheckbox3" value="option3" type="checkbox">E.取消
-                                            </label>
-                                            <label class="checkbox-inline">
-                                              <input id="inlineCheckbox3" value="option3" type="checkbox">F.纠错
-                                            </label> -->
+                                            <% } %>
                                         </div>
                                     </div>
                                     <div class="form-group">
                                         <label>变更类别 </label>
-                                        <select class="form-control form-control-sm" disabled><option>A类变更</option><option>B类变更</option><option>C类变更</option><option>D类变更</option><option>E类变更</option></select>
+                                        <select class="form-control form-control-sm" name="class" disabled>
+                                            <% for (const c in changeConst.class) { %>
+                                            <% const cClass = changeConst.class[c] %>
+                                            <option value="<%- cClass.value %>"><%- cClass.name %></option>
+                                            <% } %>
+                                        </select>
                                     </div>
                                     <div class="form-group">
                                         <label>变更性质 </label>
-                                        <select class="form-control form-control-sm" disabled><option>一般设计变更</option><option>较大设计变更</option><option>重大设计变更</option></select>
+                                        <select class="form-control form-control-sm" name="quality" disabled>
+                                            <% for (const q in changeConst.quality) { %>
+                                            <% const cQuality = changeConst.quality[q] %>
+                                            <option value="<%- cQuality.value %>"><%- cQuality.name %></option>
+                                            <% } %>
+                                        </select>
                                     </div>
                                     <div class="form-group">
                                         <label>变更提出单位</label>
-                                        <!-- <a href="#editcompany" style="float:right;" class="" data-toggle="modal">编辑</a> -->
-                                        <select class="form-control form-control-sm" disabled><option>AA公司</option><option>BB公司</option></select>
+                                        <select class="form-control form-control-sm" name="company" disabled>
+                                        </select>
                                     </div>
                                     <div class="form-group">
                                         <label>费用承担方</label>
                                         <div class="radio">
+                                            <% for (const c in changeConst.charge) { %>
+                                            <% const cCharge = changeConst.charge[c] %>
                                             <label class="radio-inline">
-                                                <input id="inlineCheckbox1" value="option1" checked="" type="radio" disabled> 业主
+                                                <input value="<%- cCharge.value %>" name="charge" type="radio" disabled> <%- cCharge.name %>
                                             </label>
-                                            <!-- <label class="radio-inline">
-                                              <input id="inlineCheckbox2" value="option2" type="radio"> 承包人
-                                            </label> -->
+                                            <% } %>
                                         </div>
                                     </div>
                                     <div class="form-group">
                                         <label>备注</label>
-                                        <textarea class="form-control form-control-sm" rows="3" readonly></textarea>
+                                        <textarea name="memo" class="form-control form-control-sm" rows="3" readonly></textarea>
                                     </div>
                                 </div>
-                                <div id="fujian" class="tab-pane">
+                                <div id="bg-fujian" class="tab-pane">
                                     <table class="table table-bordered">
+                                        <thead>
                                         <tr><th>名称</th><th>上传者</th></tr>
-                                        <tr><td><a href="">合同段工程变更现场办公会议纪要的通知.rar</a></td><th>张三</th></tr>
+                                        </thead>
+                                        <tbody id="attachment">
+                                        </tbody>
                                     </table>
                                 </div>
                             </div>