瀏覽代碼

概算控制相关

MaiXinRong 3 年之前
父節點
當前提交
f83a23957a

+ 26 - 25
app/base/base_budget_service.js

@@ -274,7 +274,7 @@ class BaseBudget extends TreeService {
             ids.push(row.id);
         }
 
-        this.transaction = await this.db.beginTransaction();
+        const conn = await this.db.beginTransaction();
         try {
             for (const row of datas) {
                 const updateNode = await this.getDataById(row.id);
@@ -292,25 +292,23 @@ class BaseBudget extends TreeService {
                 if (this._checkCalcField(row)) {
                     let calcData = JSON.parse(JSON.stringify(row));
                     if (row.quantity !== undefined || row.unit_price !== undefined) {
-                        calcData.quantity = row.quantity === undefined ? updateNode.quantity : helper.round(row.quantity, 2);
-                        calcData.unit_price = row.unit_price === undefined ? updateNode.unit_price : helper.round(row.unit_price, 2);
-                        calcData.total_price = helper.mul(calcData.quantity, calcData.unit_price, 2);
+                        calcData.quantity = row.quantity === undefined ? updateNode.quantity : helper.round(row.quantity, this.ctx.budget.decimal.qty);
+                        calcData.unit_price = row.unit_price === undefined ? updateNode.unit_price : helper.round(row.unit_price, this.ctx.budget.decimal.up);
+                        calcData.total_price = helper.mul(calcData.quantity, calcData.unit_price, this.ctx.budget.decimal.tp);
                     } else if (row.total_price !== undefined ) {
                         calcData.quantity = 0;
                         calcData.unit_price = 0;
-                        calcData.total_price = helper.round(row.total_price, 2);
+                        calcData.total_price = helper.round(row.total_price, this.ctx.budget.decimal.tp);
                     }
-                    updateData = this._filterUpdateInvalidField(updateNode.id, calcData);
+                    updateData = this._filterUpdateInvalidField(updateNode.id, this._.default(row, calcData));
                 } else {
                     updateData = this._filterUpdateInvalidField(updateNode.id, row);
                 }
-                await this.transaction.update(this.tableName, updateData);
+                await conn.update(this.tableName, updateData);
             }
-            await this.transaction.commit();
-            this.transaction = null;
+            await conn.commit();
         } catch (err) {
-            await this.transaction.rollback();
-            this.transaction = null;
+            await conn.rollback();
             throw err;
         }
 
@@ -363,14 +361,18 @@ class BaseBudget extends TreeService {
                 for (const c of d.children) {
                     c.tree_pid = newBills.tree_id;
                 }
-                if (d.b_code) {
-                    newBills.unit_price = this.ctx.helper.round(d.unit_price, 2);
-                    newBills.quantity = this.ctx.helper.round(d.quantity, 2);
-                    newBills.total_price = this.ctx.helper.mul(newBills.quantity, newBills.unit_price, 2);
+                if (d.b_code && d.is_leaf) {
+                    newBills.dgn_qty1 = 0;
+                    newBills.dgn_qty2 = 0;
+                    newBills.unit_price = this.ctx.helper.round(d.unit_price, this.ctx.budget.decimal.up);
+                    newBills.quantity = this.ctx.helper.round(d.quantity, this.ctx.budget.decimal.qty);
+                    newBills.total_price = this.ctx.helper.mul(newBills.quantity, newBills.unit_price, this.ctx.budget.decimal.tp);
                 } else {
-                    newBills.dgn_qty1 = this.ctx.helper.round(d.dgn_qty1, 2);
-                    newBills.dgn_qty2 = this.ctx.helper.round(d.dgn_qty2, 2);
-                    newBills.total_price = this.ctx.helper.round(d.total_price, 2);
+                    newBills.dgn_qty1 = this.ctx.helper.round(d.dgn_qty1, this.ctx.budget.decimal.qty);
+                    newBills.dgn_qty2 = this.ctx.helper.round(d.dgn_qty2, this.ctx.budget.decimal.qty);
+                    newBills.unit_price = 0;
+                    newBills.quantity = 0;
+                    newBills.total_price = d.is_leaf ? this.ctx.helper.round(d.total_price, this.ctx.budget.decimal.tp) : 0;
                 }
                 if (defaultData) this.ctx.helper._.assignIn(newBills, defaultData);
                 pbd.push(newBills);
@@ -406,7 +408,6 @@ class BaseBudget extends TreeService {
         return { create: pasteBillsData, update: updateData };
     }
 
-
     async importExcel(templateId, excelData, needGcl, filter) {
         const AnalysisExcel = require('../lib/analysis_excel').AnalysisExcelTree;
         const analysisExcel = new AnalysisExcel(this.ctx, this.setting, needGcl ? ['code', 'b_code'] : ['code']);
@@ -415,9 +416,9 @@ class BaseBudget extends TreeService {
             filterZeroGcl: filter, filterPos: true, filterGcl: !needGcl, filterCalc: true,
         });
         const orgMaxId = await this._getMaxLid(this.ctx.budget.id);
-        const transaction = await this.db.beginTransaction();
+        const conn = await this.db.beginTransaction();
         try {
-            await transaction.delete(this.tableName, { bid: this.ctx.budget.id });
+            await conn.delete(this.tableName, { bid: this.ctx.budget.id });
             const datas = [];
             for (const node of cacheTree.items) {
                 const data = {
@@ -444,18 +445,18 @@ class BaseBudget extends TreeService {
                 };
                 datas.push(data);
             }
-            await transaction.insert(this.tableName, datas);
-            await transaction.commit();
+            await conn.insert(this.tableName, datas);
+            await conn.commit();
             if (orgMaxId) this._cacheMaxLid(this.ctx.budget.id, cacheTree.keyNodeId);
             return datas;
         } catch (err) {
-            await transaction.rollback();
+            await conn.rollback();
             throw err;
         }
     }
 
     async getSumTp(bid) {
-        const sql = 'SELECT Sum(total_price) As total_price FROM ' + this.tableName + ' Where bid = ?';
+        const sql = 'SELECT Sum(total_price) As total_price FROM ' + this.tableName + ' Where bid = ? and is_leaf = true';
         const result = await this.db.queryOne(sql, [bid]);
         return result.total_price;
     }

+ 22 - 1
app/controller/budget_controller.js

@@ -352,8 +352,10 @@ module.exports = app => {
         }
         async detailUpdate(ctx) {
             try {
-                const relaService = this._getRelaService(ctx.params.btype);
                 if (!ctx.budget) throw '项目数据错误';
+                if (ctx.budget.readOnly) throw '你无权修改数据';
+
+                const relaService = this._getRelaService(ctx.params.btype);
                 const data = JSON.parse(ctx.request.body.data);
                 if (!data.postType || !data.postData) throw '数据错误';
                 const responseData = { err: 0, msg: '', data: {} };
@@ -389,6 +391,9 @@ module.exports = app => {
 
         async detailUploadExcel(ctx) {
             try {
+                if (!ctx.budget) throw '项目数据错误';
+                if (ctx.budget.readOnly) throw '你无权导入数据';
+
                 const relaService = this._getRelaService(ctx.params.btype);
                 const needGcl = await this._getNeedGcl();
                 const ueType = ctx.params.ueType;
@@ -412,6 +417,22 @@ module.exports = app => {
                 ctx.body = { err: 1, msg: err.toString(), data: null };
             }
         }
+
+        async decimal(ctx) {
+            try {
+                if (!ctx.budget) throw '项目数据错误';
+                if (ctx.budget.readOnly) throw '你无权修改小数位数';
+
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data || !data.decimal || !data.page) throw '缺少必要参数';
+
+                const refreshData = await ctx.service.budget.saveDecimal(data.decimal, data.page);
+                ctx.body = { err: 0, msg: '', data: refreshData };
+            } catch (err) {
+                this.log(err);
+                this.ajaxErrorBody(err, '保存小数位数失败');
+            }
+        }
     }
 
     return BudgetController;

+ 1 - 1
app/lib/analysis_excel.js

@@ -508,7 +508,7 @@ class AnalysisExcelTree {
             dgn_qty2: {value: ['设计数量2'], type: colDefineType.match},
             unit_price: {value: ['单价'], type: colDefineType.match},
             total_price: {value: ['金额', '合价'], type: colDefineType.match},
-            drawing_code: {value: ['图号'], type: colDefineType.match},
+            drawing_code: {value: ['图号', '图册号'], type: colDefineType.match},
             memo: {value: ['备注'], type: colDefineType.match},
         };
         this.needCols = needCols || ['code', 'b_code', 'pos'];

+ 1 - 1
app/middleware/budget_check.js

@@ -22,7 +22,7 @@ module.exports = options => {
             // 读取标段数据
             const id = parseInt(this.params.id);
             if (!id) throw '参数错误';
-            this.budget = yield this.service.budget.getDataById(id);
+            this.budget = yield this.service.budget.getCurBudget(id);
             if (!this.budget) throw '项目不存在';
             if (this.session.sessionUser.is_admin) {
                 this.budget.readOnly = false;

+ 73 - 2
app/public/js/budget_compare.js

@@ -47,6 +47,40 @@ $(document).ready(() => {
         rootId: -1,
     });
 
+
+    function compareCode(str1, str2, symbol = '-') {
+        if (!str1) {
+            return 1;
+        } else if (!str2) {
+            return -1;
+        }
+
+        function compareSubCode(code1, code2) {
+            if (numReg.test(code1)) {
+                if (numReg.test(code2)) {
+                    return parseInt(code1) - parseInt(code2);
+                } else {
+                    return -1
+                }
+            } else {
+                if (numReg.test(code2)) {
+                    return 1;
+                } else {
+                    return code1 === code2 ? 0 : (code1 < code2 ? -1 : 1); //code1.localeCompare(code2);
+                }
+            }
+        }
+        const numReg = /^[0-9]+$/;
+        const aCodes = str1.split(symbol), bCodes = str2.split(symbol);
+        for (let i = 0, iLength = Math.min(aCodes.length, bCodes.length); i < iLength; ++i) {
+            const iCompare = compareSubCode(aCodes[i], bCodes[i]);
+            if (iCompare !== 0) {
+                return iCompare;
+            }
+        }
+        return aCodes.length - bCodes.length;
+    }
+
     postData(window.location.pathname + '/load', {}, function (result) {
         const setting = { id: 'tree_id', pid: 'tree_pid', order: 'order', level: 'level', rootId: -1, calcFields: ['total_price'] };
         const guTree = createNewPathTree('ledger', setting);
@@ -85,11 +119,18 @@ $(document).ready(() => {
             node.gai_dgn_qty = node.gai_dgn_qty1
                 ? (node.gai_dgn_qty2 ? node.gai_dgn_qty1 + '/' + node.gai_dgn_qty2 : node.gai_dgn_qty1)
                 : (node.gai_dgn_qty2 ? '/' + node.gai_dgn_qty2 : '');
-            node.yu_dgn_price = ZhCalc.div(node.yu_tp, node.gu_dgn_qty1, 2);
+            node.yu_dgn_price = ZhCalc.div(node.yu_tp, node.yu_dgn_qty1, 2);
             node.yu_dgn_qty = node.yu_dgn_qty1
                 ? (node.yu_dgn_qty2 ? node.yu_dgn_qty1 + '/' + node.yu_dgn_qty2 : node.yu_dgn_qty1)
                 : (node.yu_dgn_qty2 ? '/' + node.yu_dgn_qty2 : '');
         });
+        compareTree.resortChildrenByCustom(function (x, y) {
+            const iCode = compareCode(x.code, y.code);
+            if (iCode) return iCode;
+            if (!x.name) return -1;
+            if (!y.name) return 1;
+            return x.name.localeCompare(y.name)
+        });
         SpreadJsObj.loadSheetData(compareSheet, SpreadJsObj.DataType.Tree, compareTree);
     });
 
@@ -173,5 +214,35 @@ $(document).ready(() => {
             SpreadJsObj.reLoadSheetData(compareSheet);
             $('#select-final').modal('hide');
         });
-    })
+    });
+    // 显示层次
+    (function (select, sheet) {
+        $(select).click(function () {
+            if (!sheet.zh_tree) return;
+            const tag = $(this).attr('tag');
+            const tree = sheet.zh_tree;
+            setTimeout(() => {
+                showWaitingView();
+                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;
+                }
+                closeWaitingView();
+            }, 100);
+        });
+    })('a[name=showLevel]', compareSheet);
 });

+ 79 - 1
app/public/js/budget_detail.js

@@ -7,6 +7,33 @@
  * @date
  * @version
  */
+
+// 根据Min Max限制Input输入
+function limitInputMinMax (obj) {
+    if (_.toNumber(obj.value) > _.toNumber(obj.max)) {
+        obj.value = obj.max;
+    }
+    if(_.toNumber(obj.value) < _.toNumber(obj.min)) {
+        obj.value = obj.min;
+    }
+}
+// 根据Maxlength限制input输入
+function limitMaxLength (obj) {
+    if (obj.value.length > obj.maxLength) {
+        obj.value = obj.value.substr(0, obj.maxLength);
+    }
+}
+// 根据正则限制输入
+function limitReg(obj, reg) {
+    obj.value = obj.value.replace(reg, '');
+}
+// 小数位数 input 输入限制
+function limitDecimal(obj) {
+    limitReg(obj, /[^\d]/g);
+    limitMaxLength(obj);
+    limitInputMinMax(obj);
+}
+
 const invalidFields = {
     parent: ['total_price', 'unit_price'],
     gcl: ['dgn_qty1', 'dgn_qty2', 'total_price'],
@@ -372,7 +399,7 @@ $(document).ready(() => {
                             data[colSetting.field] = value;
                         }
                     } else {
-                        data[colSetting.field] = colSetting.type === 'Number' ? 0 : '';
+                        data[colSetting.field] = value;
                     }
                     bPaste = true;
                 }
@@ -394,6 +421,36 @@ $(document).ready(() => {
                 SpreadJsObj.reLoadRowData(info.sheet, info.cellRange.row, info.cellRange.rowCount);
             }
         },
+        deletePress: function (sheet) {
+            const tree = sheet.zh_tree, setting = sheet.zh_setting;
+            if (!setting || !tree) return;
+
+            const sortData = sheet.zh_tree.nodes;
+            const datas = [];
+            const sel = sheet.getSelections()[0];
+            for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow++) {
+                const node = sortData[iRow];
+                if (node) {
+                    let bDel = false;
+                    const data = tree.getNodeKeyData(node);
+                    for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
+                        const style = sheet.getStyle(iRow, iCol);
+                        if (!style.locked) {
+                            const colSetting = setting.cols[iCol];
+                            data[colSetting.field] = colSetting.type === 'Number' ? 0 : '';
+                            bDel = true;
+                        }
+                    }
+                    if (bDel) datas.push(data);
+                }
+            }
+            if (datas.length > 0) {
+                postData(window.location.pathname + '/update', {postType: 'update', postData: datas}, function (result) {
+                    const refreshNode = tree.loadPostData(result);
+                    budgetTreeOpr.refreshTree(sheet, refreshNode);
+                });
+            }
+        },
         pasteBlock: function (sheet, copyInfo) {
             const self = this;
             const [tree, node] = this.getDefaultSelectInfo(sheet);
@@ -427,6 +484,7 @@ $(document).ready(() => {
         budgetSpread.bind(spreadNS.Events.EditStarting, budgetTreeOpr.editStarting);
         budgetSpread.bind(spreadNS.Events.EditEnded, budgetTreeOpr.editEnded);
         budgetSpread.bind(spreadNS.Events.ClipboardPasting, budgetTreeOpr.clipboardPasting);
+        SpreadJsObj.addDeleteBind(budgetSpread, budgetTreeOpr.deletePress);
         $.contextMenu({
             selector: '#budget-spread',
             build: function ($trigger, e) {
@@ -746,5 +804,25 @@ $(document).ready(() => {
                 }, null);
             },
         });
+    });
+
+    $('#budget-set').on('show.bs.modal', () => {
+        $('#decimal-qty').val(decimal.qty);
+        $('#decimal-up').val(decimal.up);
+        $('#decimal-tp').val(decimal.tp);
+    });
+    // 设置小数位数
+    $('#budget-set-ok').click(() => {
+        const newDecimal = {
+            qty: parseInt($('#decimal-qty').val()),
+            up: parseInt($('#decimal-up').val()),
+            tp: parseInt($('#decimal-tp').val()),
+        };
+        postData('decimal', { decimal: newDecimal, page: window.location.pathname.split('/')[3] }, result => {
+            decimal = newDecimal;
+            const refreshNodes = budgetTree.loadPostData(result);
+            budgetTreeOpr.refreshTree(budgetSheet, refreshNodes);
+            $('#budget-set').modal('hide');
+        })
     })
 });

+ 9 - 0
app/public/js/path_tree.js

@@ -1823,6 +1823,15 @@ const createNewPathTree = function (type, setting) {
                 delete x.grow_tp;
             });
         }
+        resortChildrenByCustom(fun) {
+            for (const n of this.nodes) {
+                if (n.children && n.children.length > 1) {
+                    n.children.sort(fun);
+                    n.children.forEach((x, y) => { x.order = y + 1; });
+                }
+            }
+            this.generateSortNodes();
+        }
     }
 
     if (type === 'base') {

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

@@ -1288,7 +1288,12 @@ const SpreadJsObj = {
                     canvas.fillRect(x, y, w, h);
                     canvas.restore();
                 } else {
-                    canvas.clearRect(x, y, w, h);
+                    // 不知道为什么在 概算投资-造价对比 下,这一句代码无法生效。
+                    // canvas.clearRect(x, y, w, h);
+                    canvas.save();
+                    canvas.fillStyle = 'white';
+                    canvas.fillRect(x, y, w, h);
+                    canvas.restore();
                 }
 
 

+ 1 - 0
app/router.js

@@ -590,4 +590,5 @@ module.exports = app => {
     app.post('/budget/:id/:btype/load', sessionAuth, budgetCheck, 'budgetController.detailLoad');
     app.post('/budget/:id/:btype/update', sessionAuth, budgetCheck, 'budgetController.detailUpdate');
     app.post('/budget/:id/:btype/upload-excel/:ueType', sessionAuth, budgetCheck, 'budgetController.detailUploadExcel');
+    app.post('/budget/:id/decimal', sessionAuth, budgetCheck, 'budgetController.decimal');
 };

+ 94 - 1
app/service/budget.js

@@ -7,7 +7,11 @@
  * @date 2021/11/9
  * @version
  */
-
+const defaultDecimal = {
+    qty: 3,
+    tp: 0,
+    up: 2,
+};
 
 module.exports = app => {
 
@@ -69,6 +73,13 @@ module.exports = app => {
             return result;
         }
 
+        async getCurBudget(id) {
+            const result = await this.getDataById(id);
+            result.decimal = result.decimal ? JSON.parse(result.decimal) : {};
+            this.ctx.helper._.defaults(result.decimal, defaultDecimal);
+            return result;
+        }
+
         /**
          * 新增标段
          *
@@ -151,6 +162,88 @@ module.exports = app => {
                 return false;
             }
         }
+
+        async _getGuUpdateData(newDecimal, orgDecimal) {
+            if (newDecimal.qty >= orgDecimal.qty && newDecimal.tp >= orgDecimal.tp) return [];
+            const datas = await this.ctx.service.budgetGu.getData(this.ctx.budget.id);
+            const result = [];
+            for (const d of datas) {
+                const dgn_qty1 = this.ctx.helper.round(d.dgn_qty1, newDecimal.qty);
+                const dgn_qty2 = this.ctx.helper.round(d.dgn_qty2, newDecimal.qty);
+                const total_price = d.is_leaf ? this.ctx.helper.round(d.total_price, newDecimal.tp) : 0;
+                if (dgn_qty1 !== d.dgn_qty1 || dgn_qty2 !== d.dgn_qty2 || total_price !== d.total_price) {
+                    result.push({ id: d.id, tree_id: d.tree_id, dgn_qty1, dgn_qty2, total_price });
+                }
+            }
+            return result;
+        }
+
+        async _getGaiUpdateData(newDecimal, orgDecimal) {
+            if (newDecimal.qty >= orgDecimal.qty && newDecimal.tp >= orgDecimal.tp) return [];
+            const datas = await this.ctx.service.budgetGai.getData(this.ctx.budget.id);
+            const result = [];
+            for (const d of datas) {
+                const dgn_qty1 = this.ctx.helper.round(d.dgn_qty1, newDecimal.qty);
+                const dgn_qty2 = this.ctx.helper.round(d.dgn_qty2, newDecimal.qty);
+                const total_price = d.is_leaf ? this.ctx.helper.round(d.total_price, newDecimal.tp) : 0;
+                if (dgn_qty1 !== d.dgn_qty1 || dgn_qty2 !== d.dgn_qty2 || total_price !== d.total_price) {
+                    result.push({ id: d.id, tree_id: d.tree_id, dgn_qty1, dgn_qty2, total_price });
+                }
+            }
+            return result;
+        }
+
+        async _getYuUpdateData(newDecimal, orgDecimal) {
+            if (newDecimal.qty >= orgDecimal.qty && newDecimal.up >= orgDecimal.up && newDecimal.tp === orgDecimal.tp) return [];
+            const datas = await this.ctx.service.budgetYu.getData(this.ctx.budget.id);
+            const result = [];
+            for (const d of datas) {
+                if (d.b_code) {
+                    if (!d.is_leaf) continue;
+                    const quantity = this.ctx.helper.round(d.quantity, newDecimal.qty);
+                    const unit_price = this.ctx.helper.round(d.unit_price, newDecimal.up);
+                    const total_price = this.ctx.helper.mul(unit_price, quantity, newDecimal.tp);
+                    if (quantity !== d.quantity || unit_price !== d.unit_price || total_price !== d.total_price) {
+                        result.push({ id: d.id, tree_id: d.tree_id, quantity, unit_price, total_price });
+                    }
+                } else {
+                    const dgn_qty1 = this.ctx.helper.round(d.dgn_qty1, newDecimal.qty);
+                    const dgn_qty2 = this.ctx.helper.round(d.dgn_qty2, newDecimal.qty);
+                    const total_price = d.is_leaf ? this.ctx.helper.round(d.total_price, newDecimal.tp) : 0;
+                    if (dgn_qty1 !== d.dgn_qty1 || dgn_qty2 !== d.dgn_qty2 || total_price !== d.total_price) {
+                        result.push({ id: d.id, tree_id: d.tree_id, dgn_qty1, dgn_qty2, total_price });
+                    }
+                }
+            }
+            return result;
+        }
+
+        async saveDecimal(decimal, page) {
+            const newDecimal = JSON.parse(JSON.stringify(this.ctx.budget.decimal));
+            if (decimal.qty >= 0 && decimal.qty <= 6) newDecimal.qty = decimal.qty;
+            if (decimal.up >= 0 && decimal.up <= 6) newDecimal.up = decimal.up;
+            if (decimal.tp >= 0 && decimal.tp <= 6) newDecimal.tp = decimal.tp;
+
+            const guDatas = await this._getGuUpdateData(newDecimal, this.ctx.budget.decimal);
+            const gaiDatas = await this._getGaiUpdateData(newDecimal, this.ctx.budget.decimal);
+            const yuDatas = await this._getYuUpdateData(newDecimal, this.ctx.budget.decimal);
+            const conn = await this.db.beginTransaction();
+            try {
+                const result = await conn.update(this.tableName, { id: this.ctx.budget.id, decimal: JSON.stringify(newDecimal) });
+                if (guDatas.length > 0) await conn.updateRows(this.ctx.service.budgetGu.tableName, guDatas);
+                if (gaiDatas.length > 0) await conn.updateRows(this.ctx.service.budgetGai.tableName, gaiDatas);
+                if (yuDatas.length > 0) await conn.updateRows(this.ctx.service.budgetYu.tableName, yuDatas);
+                await conn.commit();
+                switch (page) {
+                    case 'gu': return { update: guDatas };
+                    case 'gai': return { update: gaiDatas };
+                    case 'yu': return { update: yuDatas };
+                }
+            } catch (err) {
+                await conn.rollback();
+                throw err;
+            }
+        }
     }
 
     return Budget;

+ 1 - 0
app/view/budget/detail.ejs

@@ -118,4 +118,5 @@
     const readOnly = <%- ctx.budget.readOnly %>;
     const needGcl = <%- needGcl %>;
     const spreadSetting = JSON.parse('<%- JSON.stringify(spreadSetting) %>');
+    let decimal = JSON.parse('<%- JSON.stringify(ctx.budget.decimal) %>');
 </script>

+ 48 - 1
app/view/budget/detail_modal.ejs

@@ -1,2 +1,49 @@
 <% include ../shares/delete_hint_modal.ejs %>
-<% include ../shares/import_excel_modal.ejs %>
+<% include ../shares/import_excel_modal.ejs %>
+<div class="modal fade" id="budget-set" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">设置小数位数</h5>
+            </div>
+            <div class="modal-body">
+                <h6 id="del-node-hint">设置对投资估算、初步概算、施工图预算同时生效。</h6>
+                <div class="form-group">
+                    <div class="row">
+                        <div class="col-4">
+                            <div class="input-group input-group-sm">
+                                <div class="input-group-prepend">
+                                    <span class="input-group-text">数量</span>
+                                </div>
+                                <input type="number" class="form-control" id="decimal-qty"
+                                       min="0" max="4" maxlength="1" oninput="limitDecimal(this)">
+                            </div>
+                        </div>
+                        <div class="col-4">
+                            <div class="input-group input-group-sm">
+                                <div class="input-group-prepend">
+                                    <span class="input-group-text">单价</span>
+                                </div>
+                                <input type="number" class="form-control" id="decimal-up"
+                                       min="0" max="4" maxlength="1" oninput="limitDecimal(this)">
+                            </div>
+                        </div>
+                        <div class="col-4">
+                            <div class="input-group input-group-sm">
+                                <div class="input-group-prepend">
+                                    <span class="input-group-text">金额</span>
+                                </div>
+                                <input type="number" class="form-control" id="decimal-tp"
+                                       oninput="limitDecimal(this)" min="0" max="4" maxlength="1">
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-primary" id="budget-set-ok" data-dismiss="modal">确定</button>
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>

+ 3 - 0
app/view/budget/sub_menu_list.ejs

@@ -3,3 +3,6 @@
 <nav-menu title="投资估算" url="/budget/<%= ctx.budget.id %>/gu" ml="3" active="<%= ctx.url.indexOf('/gu') %>"></nav-menu>
 <nav-menu title="初步概算" url="/budget/<%= ctx.budget.id %>/gai%>" ml="3" active="<%= ctx.url.indexOf('/gai') %>"></nav-menu>
 <nav-menu title="施工图预算" url="/budget/<%= ctx.budget.id %>/yu" ml="3" active="<%= ctx.url.indexOf('/yu') %>"></nav-menu>
+<% if (!ctx.budget.readOnly && ctx.url.indexOf('/compare') === -1 ) { %>
+<div class="contarl-box"><button class="btn btn-primary btn-sm btn-block" data-toggle="modal" data-target="#budget-set">设置</button></div>
+<% } %>