浏览代码

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/YangHuCost

TonyKang 6 年之前
父节点
当前提交
84b03348d5
共有 36 个文件被更改,包括 1184 次插入578 次删除
  1. 2 1
      config/gulpConfig.js
  2. 1 1
      modules/all_models/stdRation_ration.js
  3. 1 1
      modules/all_models/std_glj.js
  4. 5 1
      modules/common/const/bills_fixed.js
  5. 12 2
      modules/complementary_glj_lib/models/gljModel.js
  6. 11 2
      modules/complementary_ration_lib/controllers/compleRationController.js
  7. 14 1
      modules/complementary_ration_lib/controllers/compleViewController.js
  8. 34 41
      modules/complementary_ration_lib/models/compleRationModel.js
  9. 7 7
      modules/complementary_ration_lib/models/searchModel.js
  10. 6 0
      modules/complementary_ration_lib/models/sectionTreeModel.js
  11. 1 0
      modules/complementary_ration_lib/routes/routes.js
  12. 1 0
      modules/pm/facade/pm_facade.js
  13. 5 2
      public/web/gljUtil.js
  14. 3 61
      web/building_saas/complementary_ration_lib/html/dinge.html
  15. 20 21
      web/building_saas/complementary_ration_lib/js/gljSelect.js
  16. 79 0
      web/building_saas/complementary_ration_lib/js/init.js
  17. 0 22
      web/building_saas/complementary_ration_lib/js/ration.js
  18. 9 30
      web/building_saas/complementary_ration_lib/js/ration_glj.js
  19. 11 17
      web/building_saas/complementary_ration_lib/js/ration_installation.js
  20. 22 51
      web/building_saas/complementary_ration_lib/js/section_tree.js
  21. 267 212
      web/building_saas/css/main.css
  22. 57 11
      web/building_saas/main/js/controllers/block_controller.js
  23. 4 0
      web/building_saas/main/js/models/bills.js
  24. 106 70
      web/building_saas/main/js/models/calc_base.js
  25. 23 8
      web/building_saas/main/js/models/calc_program.js
  26. 7 3
      web/building_saas/main/js/models/fee_rate.js
  27. 7 2
      web/building_saas/main/js/models/main_consts.js
  28. 1 0
      web/building_saas/main/js/views/calc_program_view.js
  29. 6 2
      web/building_saas/main/js/views/fee_rate_view.js
  30. 1 1
      web/building_saas/main/js/views/glj_view.js
  31. 6 1
      web/building_saas/main/js/views/glj_view_contextMenu.js
  32. 10 0
      web/building_saas/main/js/views/project_view.js
  33. 21 4
      web/building_saas/main/js/views/sub_fee_rate_views.js
  34. 1 1
      web/building_saas/pm/html/project-management.html
  35. 249 0
      web/over_write/js/neimeng_2019.js
  36. 174 2
      web/over_write/js/zhejiang_2005.js

+ 2 - 1
config/gulpConfig.js

@@ -228,7 +228,8 @@ module.exports = {
         'web/building_saas/complementary_ration_lib/js/ration_assist.js',
         'web/building_saas/complementary_ration_lib/js/ration_installation.js.js',
         'public/web/slideResize.js',
-        'web/building_saas/complementary_ration_lib/js/coe.js'
+        'web/building_saas/complementary_ration_lib/js/coe.js',
+        'web/building_saas/complementary_ration_lib/js/init.js'
     ],
     compleRation_glj_css: [
     ],

+ 1 - 1
modules/all_models/stdRation_ration.js

@@ -37,7 +37,7 @@ const rationItemSchema = new Schema({
     name: String,
     unit: String,
     basePrice: Number,
-    sectionId: Number,
+    sectionId: {type: Number,index: true},
     rationRepId: Number,
     caption: String,
     feeType: Number,

+ 1 - 1
modules/all_models/std_glj.js

@@ -21,7 +21,7 @@ const std_gljComponent = new Schema(
 const std_glj = new Schema({
     deleted: Boolean,
     repositoryId: {type: Number,index: true},
-    ID: Number,
+    ID: {type: Number,index: true},
     code: String,
     name: String,
     specs: String,

+ 5 - 1
modules/common/const/bills_fixed.js

@@ -57,7 +57,11 @@ const fixedFlag = {
     //安全生产费
     SAFE_COST:27,
     //100章清单
-    ONE_HUNDRED_BILLS: 28
+    ONE_HUNDRED_BILLS: 28,
+    // 一二三部分合计
+    ONE_TO_THREE_TOTAL: 29,
+    // 前期工作费
+    PRELIMINARY_WORK: 30,
 };
 
 export default fixedFlag;

+ 12 - 2
modules/complementary_glj_lib/models/gljModel.js

@@ -40,6 +40,16 @@ class GljDao {
             }
         }
     }
+
+    async getGLJDataSync (gljLibId, userId, compilationId) {
+        const stdGljs = await stdGljModel.find({repositoryId: gljLibId}).lean();
+        const complementaryGljs = await complementaryGljModel.find({userId, compilationId}).lean();
+        return {
+            stdGljs,
+            complementaryGljs
+        }
+    }
+
     //获得用户的补充工料机和用户当前所在编办的标准工料机
     async getGljItems (stdGljLibId, userId, compilationId, projection, callback){
         let me = this;
@@ -303,8 +313,8 @@ class GljDao {
 
     async getMixedTree(gljLibId, userId, compilationId){
         let rst = {std: [], comple: []};
-        rst.std = await gljClassModel.find({repositoryId: gljLibId});
-        rst.comple = await compleClassModel.find({userId: userId, compilationId: compilationId});
+        rst.std = await gljClassModel.find({repositoryId: gljLibId}).lean();
+        rst.comple = await compleClassModel.find({userId: userId, compilationId: compilationId}).lean();
         return rst;
     }
 }

+ 11 - 2
modules/complementary_ration_lib/controllers/compleRationController.js

@@ -9,6 +9,8 @@ let compleRationDao = new CompleRationDao();
 let coeListDAO = require('../../ration_repository/models/coe');
 const coeFacade = require('../facades/compleCoeFacade');
 const installFacade = require('../facades/compleInstallFacade');
+let gljUtil = require('../../../public/gljUtil');
+
 let callback = function (req, res, err, msg, data) {
     res.json({error: err, message: msg, data: data})
 };
@@ -89,10 +91,17 @@ class CompleRationController extends BaseController{
         let data = JSON.parse(req.body.data),
             rations = [];
         try {
+            let compilation = req.session.sessionCompilation;
+            let util = gljUtil;
+            //查看编办中有没有重写路径
+            if(compilation.overWriteUrl && compilation.overWriteUrl!=""){
+                let overWrite = require("../../.."+compilation.overWriteUrl);
+                if(overWrite.sortRationGLJ) util = overWrite;
+            }
             if (data.type === libType.complementary) {
-                rations = await compleRationDao.getCompleRationBySection(req.session.sessionUser.id, data.sectionId);
+                rations = await compleRationDao.getCompleRationBySection(req.session.sessionUser.id, data.sectionId,util);
             }  else {
-                rations = await compleRationDao.getRationGljItemsBySection(data.sectionId);
+                rations = await compleRationDao.getRationGljItemsBySection(data.sectionId,util);
             }
             callback(req, res, 0, 'success', rations);
         } catch (err) {

+ 14 - 1
modules/complementary_ration_lib/controllers/compleViewController.js

@@ -6,8 +6,9 @@ import BaseController from '../../common/base/base_controller';
 import CompleViewModel from '../models/compleViewModel';
 import EngineeringLibModel from "../../users/models/engineering_lib_model";
 let config = require("../../../config/config.js");
-
 let compleViewModel = new CompleViewModel();
+import CompleRationDao from '../models/compleRationModel';
+const compleRationDao = new CompleRationDao();
 let callback = function (req, res, err, msg, data) {
     res.json({error: err, message: msg, data: data});
 };
@@ -53,6 +54,18 @@ class CompleViewController extends BaseController{
         });
     }
 
+    async prepareInitData (req, res) {
+        try {
+            const gljLibId = await getGljLibId(req.session.sessionCompilation);
+            const userId = req.session.sessionUser.id;
+            const compilationId = req.session.sessionCompilation._id;
+            const initData = await compleRationDao.prepareInitData(userId, compilationId, gljLibId);
+            res.json({error: 0, message: 'success', data: initData});
+        } catch (err) {
+            res.json({error: 1, message: 'fail', data: null});
+        }
+    }
+
     async redirectGljList(req, res){
         const gljLibId = await getGljLibId(req.session.sessionCompilation);
         const redirectRation = `/complementaryRation/ration`;

+ 34 - 41
modules/complementary_ration_lib/models/compleRationModel.js

@@ -8,10 +8,17 @@ const installSectionModel = mongoose.model("std_ration_lib_installationSection")
 const installFeeItemModel = mongoose.model("std_ration_lib_installation");
 const complementaryGljModel = mongoose.model('complementary_glj_lib');
 const stdGljModel = mongoose.model('std_glj_lib_gljList');
+const stdgljutil = require('../../../public/cache/std_glj_type_util');
+const installFacade = require('../facades/compleInstallFacade');
 import async from 'async';
 let stdRationModel = require ('../../ration_repository/models/ration_item').Model;
+import SectionTreeDao from '../models/sectionTreeModel';
+const sectionTreeDao = new SectionTreeDao();
+import GljDao from "../../complementary_glj_lib/models/gljModel";
+const gljDao = new GljDao();
 let counter = require('../../../public/counter/counter');
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
+let gljUtil = require('../../../public/gljUtil');
 
 class CompleRatoinDao {
     async updateRation(userID, compilationId, updateData, callback){
@@ -131,7 +138,7 @@ class CompleRatoinDao {
     }
 
     //根据章节树获取补充定额
-    async getCompleRationBySection(userId, sectionId) {
+    async getCompleRationBySection(userId, sectionId,gUtil) {
         const deleteQuery = [{deleteInfo: null}, {'deleteInfo.deleted': false}];
         let compleRations = await compleRationModel.find({sectionId: sectionId, $or: deleteQuery});
         for(let ration of compleRations){
@@ -157,17 +164,8 @@ class CompleRatoinDao {
             if(comGljIds.length > 0) {
                 comGljs = await complementaryGljModel.find({userId: userId, ID: {$in: comGljIds}});
             }
-            let gljDatas = stdGljs.concat(comGljs);
-            gljDatas.sort(function (a, b) {
-                let aV = a.gljType + a.code,
-                    bV = b.gljType + b.code;
-                if(aV > bV) {
-                    return 1;
-                } else if (aV < bV) {
-                    return -1;
-                }
-                return 0;
-            });
+            if(!gUtil) gUtil = gljUtil;
+            let gljDatas = gUtil.sortRationGLJ(stdGljs.concat(comGljs));
             for(let glj of gljDatas){
                 hintsArr.push(` ${glj.code} ${glj.name}${glj.specs ? '&nbsp;&nbsp;&nbsp;' + glj.specs : ''}&nbsp;&nbsp&nbsp;${glj.unit}&nbsp;&nbsp;&nbsp;${gljAmtMapping[glj.ID]}`)
             }
@@ -186,7 +184,7 @@ class CompleRatoinDao {
     }
 
     //造价书定额库 根据章节树过去标准定额
-    async getRationGljItemsBySection(sectionId, callback){
+    async getRationGljItemsBySection(sectionId,gUtil){
         let stdRations = await stdRationModel.find({sectionId: sectionId});
         for(let ration of stdRations){
             ration._doc.type = 'std';
@@ -243,17 +241,8 @@ class CompleRatoinDao {
             if(stdGljIds.length > 0) {
                 stdGljs = await stdGljModel.find({ID: {$in: stdGljIds}});
             }
-            let gljDatas = stdGljs;
-            gljDatas.sort(function (a, b) {
-                let aV = a.gljType + a.code,
-                    bV = b.gljType + b.code;
-                if(aV > bV) {
-                    return 1;
-                } else if (aV < bV) {
-                    return -1;
-                }
-                return 0;
-            });
+            if(!gUtil) gUtil = gljUtil;
+            let gljDatas =  gUtil.sortRationGLJ(stdGljs);
             for(let glj of gljDatas){
                 hintsArr.push(` ${glj.code} ${glj.name}${glj.specs ? '&nbsp;&nbsp;&nbsp;' + glj.specs : ''}&nbsp;&nbsp&nbsp;${glj.unit}&nbsp;&nbsp;&nbsp;${gljAmtMapping[glj.ID]}`)
             }
@@ -475,23 +464,27 @@ class CompleRatoinDao {
         });
     }
 
-    async getInstallation(rationRepId, callback){
-        try {
-            let feeItems = await installFeeItemModel.find({rationRepId: rationRepId, $or: [{deleted: false}, {deleted: null}]});
-            for(let feeItem of feeItems){
-                let sids = [];
-                for(let sec of feeItem.section){
-                    sids.push(sec.ID);
-                }
-                if(sids.length > 0){
-                    let sections = await installSectionModel.find({ID: {$in: sids}, $or: [{deleted: false}, {deleted: null}]});
-                    feeItem._doc.section = sections;
-                }
-            }
-            callback(0, feeItems);
-        }
-        catch(err){
-            callback(err, null);
+    async getCodes (userId, compilationId) {
+        const compleRations = await compleRationModel.find({userId, compilationId}, '-_id code').lean();
+        const codes = [];
+        compleRations.forEach(item => codes.push(item.code));
+        return codes;
+    }
+
+    async prepareInitData (userId, compilationId, gljLibId) {
+        const rationsCodes = await this.getCodes(userId, compilationId);
+        const gljDistTypeCache = stdgljutil.getStdGljTypeCacheObj().toArray();
+        const installationData = await installFacade.getInstallation(userId, compilationId);
+        const rationTreeData = await sectionTreeDao.getComplementaryTree(userId, compilationId);
+        const mixedTreeData = await gljDao.getMixedTree(gljLibId, userId, compilationId);
+        const mixedGLJData = await gljDao.getGLJDataSync(gljLibId, userId, compilationId);
+        return {
+            rationsCodes,
+            gljDistTypeCache,
+            installationData,
+            rationTreeData,
+            mixedTreeData,
+            mixedGLJData
         }
     }
 }

+ 7 - 7
modules/complementary_ration_lib/models/searchModel.js

@@ -14,13 +14,13 @@ const compleRationLib = 'compleRationLib';
 class SearchDao{
     async getRationItem(userId, compilationId, rationRepIds, code, ID, callback){
         let ration = null;
+        let otherLibs=[];
         try{
-            let firstLib = rationRepIds.shift();//优先取第一个
-            if(rationRepIds.includes(firstLib)) {//去掉重复的库ID
-                rationRepIds.splice(rationRepIds.indexOf(firstLib), 1);
-            }
-            if(rationRepIds.includes(compleRationLib)) {
-                rationRepIds.splice(rationRepIds.indexOf(compleRationLib), 1);
+            let firstLib = rationRepIds[0];//优先取第一个
+            for (let l of rationRepIds){
+                if(l != firstLib && l != compleRationLib){
+                    otherLibs.push(l);
+                }
             }
             if(firstLib == compleRationLib){//说明选中的是补充定额库
                 ration = await this.getCompleRation(userId,compilationId,code,ID);
@@ -33,7 +33,7 @@ class SearchDao{
                 ration = await this.getStdRation(firstQuery);
             }
             if(ration == null){//选中的定额库或者默认的定额库中没有找到定额,才走常规的流程查找其它定额库
-                let stdQuery = {rationRepId: {$in: rationRepIds}, code: code, $or: [{isDeleted: null}, {isDeleted: false}]};
+                let stdQuery = {rationRepId: {$in: otherLibs}, code: code, $or: [{isDeleted: null}, {isDeleted: false}]};
                 if(ID){
                     stdQuery = {ID: ID, $or: [{isDeleted: null}, {isDeleted: false}]};
                 }

+ 6 - 0
modules/complementary_ration_lib/models/sectionTreeModel.js

@@ -48,6 +48,12 @@ class SectionTreeDao {
         });
 
     }
+
+    async getComplementaryTree (userId, compilationId) {
+        const treeData = await compleRationSectionTreeModel.find({userId, compilationId}).lean();
+        return treeData;
+    }
+
     async getRationTree(userId, compilationId, rationRepId, type, callback) {
         //区分要获取的是标准的数据还是补充的数据
         const rationLibType = {

+ 1 - 0
modules/complementary_ration_lib/routes/routes.js

@@ -21,6 +21,7 @@ module.exports = function (app) {
     app.get('/complementaryRation/glj', compleViewController.init, compleViewController.redirectGljList);
     app.get('/complementaryRation/coe', compleViewController.init, compleViewController.redirectCoeList);
     app.get('/complementaryRation/installation', compleViewController.init, compleViewController.redirectInstallation);
+    router.get('/initData', compleViewController.init, compleViewController.prepareInitData);
 
     router.post('/getRationLib', compleViewController.init, compleViewController.getRationLib);
     router.post('/getRationLibs', compleViewController.init, compleViewController.getRationLibs);

+ 1 - 0
modules/pm/facade/pm_facade.js

@@ -1234,6 +1234,7 @@ async function handleMainProjectDatas(mainData,updateData,userID) {
     let mainProjectID = -1;
     let projectIDMap = {},feeRateFileIDMap={},unitPriceFileIDMap={},labourCoeFileIDMap={},calcProgramFileIDMap={};
     let tasks = [];
+    projectIDMap[-1] = -1;//最后一个项目的nextID为-1的情况
     //生成新的projectID
     for(let p of mainData.projects){
         let newProjectID = await getCounterID("projects");

+ 5 - 2
public/web/gljUtil.js

@@ -331,7 +331,7 @@ let gljUtil = {
     sortRationGLJ:function (list) {
         list = _.sortByAll(list, [function (item) {
             return gljUtil.getMainType(item.type);
-        }, "code"]);
+        }, gljUtil.getCodeSortMath()]);
         return list;
     },
     sortMixRatio:function (list) {
@@ -344,9 +344,12 @@ let gljUtil = {
         list = lo.sortByAll(list, [function (item) {
             if(specialMap[item.unit_price.type] != undefined) return specialMap[item.unit_price.type];
             return gljUtil.getMainType(item.unit_price.type);
-        }, "code"]);
+        }, gljUtil.getCodeSortMath()]);
         return list;
     },
+    getCodeSortMath:function () {
+      return "code"
+    },
     isConcreteType:function (type) {
         let concreteType = [gljUtil.gljType.CONCRETE,gljUtil.gljType.MORTAR,gljUtil.gljType.MIX_RATIO];//混凝土大类:混凝土、砂浆,配合比
         return concreteType.indexOf(type)!=-1

+ 3 - 61
web/building_saas/complementary_ration_lib/html/dinge.html

@@ -52,7 +52,8 @@
         }
     </style>
     <script>
-        let gljLibId = '<%= gljLibId %>';
+        const gljLibId = '<%= gljLibId %>';
+        const userID = '<%=userID %>';
     </script>
 </head>
 <body>
@@ -630,67 +631,8 @@
 <script type="text/javascript" src="/web/building_saas/complementary_ration_lib/js/ration_installation.js"></script>
 <script src="/public/web/slideResize.js"></script>
 <script src="/web/building_saas/complementary_ration_lib/js/coe.js"></script>
+<script src="/web/building_saas/complementary_ration_lib/js/init.js"></script>
 <!--endinject-->
-<script type="text/javascript">
-    let userID = '<%=userID %>';
-    $(document).ready(function(){
-        rationOprObj.buildSheet($("#rationItemsSheet")[0]);
-
-        // tabPanel 下有多个Spread时,相互之间不能正确显示。改成一个Spread下多个Sheet。
-        var rdSpread = sheetCommonObj.createSpread($("#rdSpread")[0], 4);
-        rdSpread.options.allowUserDragFill = false;
-        rdSpread.options.allowUserDragDrop = false;
-        sheetCommonObj.spreadDefaultStyle(rdSpread);
-        rationGLJOprObj.buildSheet(rdSpread.getSheet(0));
-
-        rationAssistOprObj.buildSheet(rdSpread.getSheet(1));
-
-        rationCoeOprObj.buildSheet(rdSpread.getSheet(2));
-
-        rationInstObj.buildSheet(rdSpread.getSheet(3));
-        rationInstObj.getInstallation(parseInt(getQueryString("repository")), function () {
-            //rationInstObj.buildSheet(rdSpread.getSheet(3));
-        });
-        let rdSpreadEscSheets = [];
-        rdSpreadEscSheets.push({sheet: rdSpread.getSheet(0), editStarting: rationGLJOprObj.onEditStarting, editEnded: rationGLJOprObj.onCellEditEnd});
-        rdSpreadEscSheets.push({sheet: rdSpread.getSheet(1), editStarting: rationAssistOprObj.onEditStarting, editEnded: rationAssistOprObj.onEditEnded});
-        rdSpreadEscSheets.push({sheet: rdSpread.getSheet(2), editStarting: rationCoeOprObj.onEditStarting, editEnded: rationCoeOprObj.onEditEnded});
-        rdSpreadEscSheets.push({sheet: rdSpread.getSheet(3), editStarting: rationInstObj.onEditStarting, editEnded: rationInstObj.onEditEnded});
-        sheetCommonObj.bindEscKey(rdSpread, rdSpreadEscSheets);
-        pageOprObj.initPage();
-
-        $("#linkGLJ").click(function(){
-            rationGLJOprObj.bindRationGljDelOpr();
-            rdSpread.setActiveSheetIndex(0);
-        });
-
-        $("#linkFZDE").click(function(){
-            rationAssistOprObj.bindRationAssDel();
-            rdSpread.setActiveSheetIndex(1);
-        });
-
-        $("#linkFZTJ").click(function(){
-            rationCoeOprObj.bindRationCoeDel();
-            rdSpread.setActiveSheetIndex(2);
-        });
-
-        $("#linkAZZJ").click(function(){
-            rationInstObj.bindRationInstDel();
-            rdSpread.setActiveSheetIndex(3);
-        });
-        //解决spreadjs sheet初始化没高度宽度
-        $('#modalCon').width($(window).width()*0.5);
-        $('#gljSelTreeDiv').height($(window).height() - 300);
-        $("#gljSelSheet").height($("#gljSelTreeDiv").height()-21.6);
-        $("#gljSelSheet").width($('#modalCon').width() * 0.63);
-        $(window).resize(function () {
-            $('#modalCon').width($(window).width()*0.5);
-            $('#gljSelTreeDiv').height($(window).height() - 300);
-            $("#gljSelSheet").height($("#gljSelTreeDiv").height()-21.6);
-            $("#gljSelSheet").width($('#modalCon').width()* 0.63);
-        });
-    });
-</script>
 </body>
 <script type="text/javascript">
     autoFlashHeight();

+ 20 - 21
web/building_saas/complementary_ration_lib/js/gljSelect.js

@@ -39,28 +39,22 @@ let gljSelOprObj = {
             delete glj.ID;
         }
     },
-    getSelGljItems: function(stdGljLibId, callback) {
-        let me = this;
-        CommonAjax.post('/complementartGlj/api/getGljItems', {stdGljLibId: stdGljLibId}, function (rstData) {
-            me.stdGljList = rstData.stdGljs;
-            //兼容多单价,计算补充定额价格时,套多单价人材机的时候,默认取第一个价格
-            for(let sGlj of me.stdGljList){
-                if(sGlj.priceProperty && typeof sGlj.priceProperty.price1 !== 'undefined'){
-                    sGlj.basePrice = sGlj.priceProperty.price1;
-                }
-            }
-            me.complementaryGljList = rstData.complementaryGljs;
-            me.switchToGljId(me.stdGljList);
-            me.switchToGljId(me.complementaryGljList);
-            me.setProp('type', 'std', me.stdGljList);
-            me.setProp('type', 'complementary', me.complementaryGljList);
-            me.sortGlj(me.stdGljList);
-            me.sortGlj(me.complementaryGljList);
-            gljAdjOprObj.gljList = me.stdGljList.concat(me.complementaryGljList);
-            if(callback){
-                callback();
+    getSelGljItems: function(gljData) {
+        this.stdGljList = gljData.stdGljs;
+        //兼容多单价,计算补充定额价格时,套多单价人材机的时候,默认取第一个价格
+        for(let sGlj of this.stdGljList){
+            if(sGlj.priceProperty && typeof sGlj.priceProperty.price1 !== 'undefined'){
+                sGlj.basePrice = sGlj.priceProperty.price1;
             }
-        });
+        }
+        this.complementaryGljList = gljData.complementaryGljs;
+        this.switchToGljId(this.stdGljList);
+        this.switchToGljId(this.complementaryGljList);
+        this.setProp('type', 'std', this.stdGljList);
+        this.setProp('type', 'complementary', this.complementaryGljList);
+        this.sortGlj(this.stdGljList);
+        this.sortGlj(this.complementaryGljList);
+        gljAdjOprObj.gljList = this.stdGljList.concat(this.complementaryGljList);
     },
     initClassTree: function (type, treeData) {
         let me = this;
@@ -98,6 +92,11 @@ let gljSelOprObj = {
         };
         CommonAjax.post(url, postData, sucFunc, errFunc);
     },
+    getGljClassTree: function (mixedTreeData) {
+        this.treeData = mixedTreeData;
+        this.initClassTree('std', this.treeData.std);
+        gljSelOprObj.buildSheet($('#gljSelSheet')[0]);
+    },
     buildSheet: function (container) {
         let me = gljSelOprObj;
         me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30);

+ 79 - 0
web/building_saas/complementary_ration_lib/js/init.js

@@ -0,0 +1,79 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/9/24
+ * @version
+ */
+const initialization = (() => {
+    $(document).ready(function () {
+        $.bootstrapLoading.start();
+        CommonAjax.get('/complementaryRation/api/initData', {}, res => {
+            if (res.error) {
+                alert('数据初始化失败,请重试。');
+                setTimeout(() => {
+                    window.location.href = '/'
+                }, 1200);
+            } else {
+                const data = res.data;
+                pageOprObj.rationTreeData = data.rationTreeData;
+                pageOprObj.mixedTreeData = data.mixedTreeData;
+                pageOprObj.mixedGLJData = data.mixedGLJData;
+                rationGLJOprObj.distTypeTree = data.gljDistTypeCache;
+                rationOprObj.rationsCodes = data.rationsCodes;
+                rationOprObj.buildSheet($("#rationItemsSheet")[0]);
+                // tabPanel 下有多个Spread时,相互之间不能正确显示。改成一个Spread下多个Sheet。
+                var rdSpread = sheetCommonObj.createSpread($("#rdSpread")[0], 4);
+                rdSpread.options.allowUserDragFill = false;
+                rdSpread.options.allowUserDragDrop = false;
+                sheetCommonObj.spreadDefaultStyle(rdSpread);
+                rationGLJOprObj.buildSheet(rdSpread.getSheet(0));
+                rationAssistOprObj.buildSheet(rdSpread.getSheet(1));
+                rationCoeOprObj.buildSheet(rdSpread.getSheet(2));
+                rationInstObj.buildSheet(rdSpread.getSheet(3));
+                rationInstObj.getInstallation(data.installationData);
+                let rdSpreadEscSheets = [];
+                rdSpreadEscSheets.push({sheet: rdSpread.getSheet(0), editStarting: rationGLJOprObj.onEditStarting, editEnded: rationGLJOprObj.onCellEditEnd});
+                rdSpreadEscSheets.push({sheet: rdSpread.getSheet(1), editStarting: rationAssistOprObj.onEditStarting, editEnded: rationAssistOprObj.onEditEnded});
+                rdSpreadEscSheets.push({sheet: rdSpread.getSheet(2), editStarting: rationCoeOprObj.onEditStarting, editEnded: rationCoeOprObj.onEditEnded});
+                rdSpreadEscSheets.push({sheet: rdSpread.getSheet(3), editStarting: rationInstObj.onEditStarting, editEnded: rationInstObj.onEditEnded});
+                sheetCommonObj.bindEscKey(rdSpread, rdSpreadEscSheets);
+                pageOprObj.initPage();
+
+                $("#linkGLJ").click(function(){
+                    rationGLJOprObj.bindRationGljDelOpr();
+                    rdSpread.setActiveSheetIndex(0);
+                });
+
+                $("#linkFZDE").click(function(){
+                    rationAssistOprObj.bindRationAssDel();
+                    rdSpread.setActiveSheetIndex(1);
+                });
+
+                $("#linkFZTJ").click(function(){
+                    rationCoeOprObj.bindRationCoeDel();
+                    rdSpread.setActiveSheetIndex(2);
+                });
+
+                $("#linkAZZJ").click(function(){
+                    rationInstObj.bindRationInstDel();
+                    rdSpread.setActiveSheetIndex(3);
+                });
+            }
+            $.bootstrapLoading.end();
+        });
+        //解决spreadjs sheet初始化没高度宽度
+        $('#modalCon').width($(window).width()*0.5);
+        $('#gljSelTreeDiv').height($(window).height() - 300);
+        $("#gljSelSheet").height($("#gljSelTreeDiv").height()-21.6);
+        $("#gljSelSheet").width($('#modalCon').width() * 0.63);
+        $(window).resize(function () {
+            $('#modalCon').width($(window).width()*0.5);
+            $('#gljSelTreeDiv').height($(window).height() - 300);
+            $("#gljSelSheet").height($("#gljSelTreeDiv").height()-21.6);
+            $("#gljSelSheet").width($('#modalCon').width()* 0.63);
+        });
+    });
+})();

+ 0 - 22
web/building_saas/complementary_ration_lib/js/ration.js

@@ -92,7 +92,6 @@ let rationOprObj = {
         let me = rationOprObj;
         me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30);
         sheetCommonObj.bindEscKey(me.workBook, [{sheet: me.workBook.getSheet(0), editStarting: me.onCellEditStart, editEnded: me.onCellEditEnd}]);
-        me.getRationsCodes(rationRepId);
         me.onContextmenuOpr();
         me.rationDelOpr();
         me.setCombo(me.workBook.getSheet(0), 'dynamic');
@@ -617,27 +616,6 @@ let rationOprObj = {
         obj.machinePrice = 0;
         obj.basePrice = 0;
     },
-    isValidUnit: function (rationObj, validUnits) {
-        let rst = true;
-        if(typeof rationObj.unit !== 'undefined' && rationObj.unit && validUnits.indexOf(rationObj.unit) === -1){//无效
-            rst = false;
-        }
-        return rst;
-    },
-    getRationsCodes: function (repId) {
-        let me = rationOprObj;
-        $.ajax({
-            type: 'post',
-            url: 'api/getRationsCodes',
-            data: {data: JSON.stringify({repId: repId})},
-            dataType: 'json',
-            success: function (result) {
-                if(!result.error){
-                    me.rationsCodes = result.data;
-                }
-            }
-        })
-    },
     mixUpdateRequest: function(updateArr, addArr, removeIds, callback) {
         let me = rationOprObj;
         me.saveInString(updateArr);

+ 9 - 30
web/building_saas/complementary_ration_lib/js/ration_glj.js

@@ -25,7 +25,6 @@ var rationGLJOprObj = {
         }
     },
     getDistTypeTree: function (gljDistType) {
-        let me = this;
         let distType;
         let distTypeTree = {
             prefix : 'gljDistType',
@@ -61,36 +60,16 @@ var rationGLJOprObj = {
         });
         return distTypeTree;
     },
-    getGljDistType: function (callback) {
-        let me = this;
-        $.ajax({
-            type: 'post',
-            url: "api/getGljDistType",
-            dataType: 'json',
-            success: function (result) {
-                if(!result.error && callback){
-                    me.distTypeTree = me.getDistTypeTree(result.data);
-                    callback();
-                }
-            }
-        })
-    },
     buildSheet: function(sheet) {
-        var me = this;
-        me.sheet = sheet;
-        me.getGljDistType(function () {
-           // gljSelOprObj.getGljClassTree(pageOprObj.gljLibId, function () {
-              //  gljSelOprObj.getSelGljItems(pageOprObj.gljLibId, function () {
-                    sheetCommonObj.initSheet(me.sheet, me.setting, 30);
-                    me.onContextmenuOpr();
-                    me.bindRationGljDelOpr();
-                    me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
-                    me.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, me.onClipboardPasted);
-                    me.sheet.bind(GC.Spread.Sheets.Events.EditStarting, me.onEditStarting);
-                    me.sheet.bind(GC.Spread.Sheets.Events.EditEnded, me.onCellEditEnd);
-                });
-          //  });
-        //});
+        this.sheet = sheet;
+        this.distTypeTree = this.getDistTypeTree(this.distTypeTree);
+        sheetCommonObj.initSheet(this.sheet, this.setting, 30);
+        this.onContextmenuOpr();
+        this.bindRationGljDelOpr();
+        this.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasting, this.onClipboardPasting);
+        this.sheet.bind(GC.Spread.Sheets.Events.ClipboardPasted, this.onClipboardPasted);
+        this.sheet.bind(GC.Spread.Sheets.Events.EditStarting, this.onEditStarting);
+        this.sheet.bind(GC.Spread.Sheets.Events.EditEnded, this.onCellEditEnd);
     },
     onContextmenuOpr: function () {//右键菜单
         let me = this;

+ 11 - 17
web/building_saas/complementary_ration_lib/js/ration_installation.js

@@ -42,24 +42,18 @@ let rationInstObj = {
     isDef: function (v) {
         return v !== undefined && v !== null;
     },
-    getInstallation: function (callback) {
-        let me = this;
-        CommonAjax.post('api/getInstallation', {}, function (rstData) {
-            //建立name - ID 映射, ID - name 映射
-            me.feeItem = {};
-            me.IDMapping = {feeItem: {}, section: {}};
-            for(let feeItem of rstData){
-                me.feeItem[feeItem.feeItem] = {ID: feeItem.ID, section: {}};
-                me.IDMapping['feeItem'][feeItem.ID] = feeItem.feeItem;
-                for(let section of feeItem.section){
-                    me.feeItem[feeItem.feeItem]['section'][section.name] = section.ID;
-                    me.IDMapping['section'][section.ID] = section.name;
-                }
-            }
-            if(callback){
-                callback(rstData);
+    getInstallation: function (installationData) {
+        //建立name - ID 映射, ID - name 映射
+        this.feeItem = {};
+        this.IDMapping = {feeItem: {}, section: {}};
+        for(let feeItem of installationData){
+            this.feeItem[feeItem.feeItem] = {ID: feeItem.ID, section: {}};
+            this.IDMapping['feeItem'][feeItem.ID] = feeItem.feeItem;
+            for(let section of feeItem.section){
+                this.feeItem[feeItem.feeItem]['section'][section.name] = section.ID;
+                this.IDMapping['section'][section.ID] = section.name;
             }
-        });
+        }
     },
     getFeeItemCombo: function () {
         let feeItemArr = [];

+ 22 - 51
web/building_saas/complementary_ration_lib/js/section_tree.js

@@ -2,31 +2,14 @@
  * Created by Zhong on 2017/12/18.
  */
 let pageOprObj = {
-    refreshAllBooks: function () {
-        if (sectionTreeObj.workBook) {
-            sectionTreeObj.workBook.refresh();
-        }
-        if (rationOprObj.workBook) {
-            rationOprObj.workBook.refresh();
-        }
-        if (coeOprObj.workBook) {
-            coeOprObj.workBook.refresh();
-        } else {
-            pageObj.initPage();
-        }
-        if (gljAdjOprObj.workBook) {
-            gljAdjOprObj.workBook.refresh();
-        }
-        if (rationGLJOprObj.sheet.getParent()) {
-            rationGLJOprObj.sheet.getParent().refresh();
-        }
-    },
     rationLibName : null,
     rationLibId : null,
     gljLibId: gljLibId,
+    rationTreeData: null,
+    mixedTreeData: null,
+    mixedGLJData: null,
     initPage : function() {
-        let me = this;
-        sectionTreeObj.getSectionTree();
+        sectionTreeObj.getSectionTree(this.rationTreeData);
         //job
         jobContentOprObj.radiosChange(jobContentOprObj.radios, jobContentOprObj.tableAll, jobContentOprObj.tablePartial);
         $('#addConBtn').click(jobContentOprObj.bindAddConBtn());
@@ -37,9 +20,8 @@ let pageOprObj = {
         $('#fzAddConBtn').click(annotationOprObj.bindAddConBtn());
         $('#fzUpdateConBtn').click(annotationOprObj.bindUpdateConBtn());
         annotationOprObj.bindAllEvents($('#fzTxtareaAll'));
-        gljSelOprObj.getGljClassTree(gljLibId, function () {
-            gljSelOprObj.getSelGljItems(gljLibId);
-        });
+        gljSelOprObj.getGljClassTree(this.mixedTreeData);
+        gljSelOprObj.getSelGljItems(this.mixedGLJData);
     },
     getRationLibInfo: function (rationLibId, callback) {
         CommonAjax.post('api/getRationLib', {rationRepId: rationLibId}, callback);
@@ -223,32 +205,21 @@ let sectionTreeObj = {
             sheetCommonObj.setColumnWidthByRate($('#sectionSpread').width() - 65, this.workBook, [{rateWidth: 1}]);//65: 列头宽度和垂直滚动条宽度和
         }
     },
-    getSectionTree: function () {
-        let me = sectionTreeObj;
-        let url = 'api/getRationTree';
-        //type: 0-补充库 1-标准库
-        let postData = {type: 0};
-        let sucFunc = function (rstData) {
-            if(rstData.length > 0){
-                storageUtil.setSessionCache("RationGrp","repositoryID",rstData[0].rationRepId);
-            }
-            //init
-            me.buildSheet();
-            me.initTree(rstData);
-            me.cache = me.tree.items;
-            me.bindBtn();
-            me.initController(me.tree, me.sheet, me.setting.sheet);
-            me.controller.showTreeData();
-            me.setColor(me.cache);
-            me.sheet.setFormatter(-1, 0, '@');
-            me.initSelection(me.tree.selected);
-            me.loadRateWidth();
-            //explanatoryOprObj.bindEvents($('#explanationShow'), $('#ruleTextShow'));
-        };
-        let errFunc = function () {
-
-        };
-        CommonAjax.post(url, postData, sucFunc, errFunc);
+    getSectionTree: function (treeData) {
+        /*if(rstData.length > 0){
+            storageUtil.setSessionCache("RationGrp","repositoryID",rstData[0].rationRepId);
+        }*/
+        //init
+        this.buildSheet();
+        this.initTree(treeData);
+        this.cache = this.tree.items;
+        this.bindBtn();
+        this.initController(this.tree, this.sheet, this.setting.sheet);
+        this.controller.showTreeData();
+        this.setColor(this.cache);
+        this.sheet.setFormatter(-1, 0, '@');
+        this.initSelection(this.tree.selected);
+        this.loadRateWidth();
     },
 
     setColor: function (nodes) {
@@ -578,7 +549,6 @@ let sectionTreeObj = {
     },
     //模仿默认点击
     initSelection: function (node) {
-        node.tree.selected = node ? node : null;
         let me = this;
         if(!me.isDef(node)){
             sheetCommonObj.cleanSheet(rationOprObj.workBook.getActiveSheet(), rationOprObj.setting, -1);
@@ -588,6 +558,7 @@ let sectionTreeObj = {
             sheetCommonObj.cleanSheet(rationInstObj.sheet, rationInstObj.setting, -1);
             return;
         }
+        node.tree.selected = node ? node : null
         me.workBook.getActiveSheet().setActiveCell(node.serialNo(), 0);
         me.initTools(node);
         me.refreshBtn(node);

+ 267 - 212
web/building_saas/css/main.css

@@ -3,71 +3,88 @@
 body {
     font-size: 0.9rem;
     overflow: hidden;
+    font-family: "Helvetica Neue","Hiragino Sans GB",stheiti,"Microsoft Yahei","微软雅黑",tahoma,sans-serif
 }
 a{
-    outline: none
+  outline: none
 }
 .dropdown-menu {
     font-size: 0.9rem
 }
 .btn.disabled, .btn:disabled {
-    color:#999
+  color:#999
 }
 .btn-link:focus, .btn-link:hover{
-    text-decoration: none
+  text-decoration: none
 }
 .dropdown-menu {
-    padding:.2rem 0;
+  padding:.2rem 0;
 }
 .dropdown-item:focus, .dropdown-item:hover{
-    background-color: #f7f7f9
+  background-color: #f7f7f9
 }
 .text-indent {
-    text-indent:26px;
+  text-indent:26px;
 }
 .modal-header{
-    background:#f2f2f2;
-    border-bottom:1px solid #ccc;
-    padding:.8rem 1rem;
+  background:#f2f2f2;
+  border-bottom:1px solid #ccc;
+  padding:.8rem 1rem;
 }
 .modal-title{
-    font-size:1rem;
+  font-size:1rem;
 }
 .modal-footer{
-    padding:.8rem 1rem;
+  padding:.8rem 1rem;
 }
 .form-check .form-check-label,.form-radio .form-check-label{
-    cursor: pointer;
+  cursor: pointer;
+}
+.custom-file-sm,.custom-file-sm .custom-file-label{
+  height: calc(1.5em + .5rem + 2px);
+  padding-top: .25rem;
+  padding-bottom: .25rem;
+  padding-left: .5rem;
+}
+.custom-file-sm .custom-file-label:after{
+  height: calc(1.4em + .5rem + 2px);
+padding-top: .25rem;
+padding-bottom: .25rem;
+font-size: .875rem;
+}
+.custom-file-sm input{
+  height: calc(1.5em + .5rem + 2px);
+font-size: .875rem;
 }
 /*自定义css*/
 .login-body,.login-html{
-    height:100%;
+  height:100%;
 }
 .login-bg{
-    width: 100%;
-    height: 100%;
-    background: #f2f6f5 url("login-bg.jpg") bottom center no-repeat;
-    background-size: 100% auto;
-    display: inline-block;
-    position: absolute;
+  width: 100%;
+  height: 100%;
+  background: #f2f6f5 url("login-bg.jpg") bottom center no-repeat;
+  background-size: 100% auto;
+  display: inline-block;
+  position: absolute;
 }
 .login-panel {
-    width: 500px;
-    margin: 0 auto;
-    position: absolute;
-    left: 0;
-    right: 0;
-    top: 20%;
-    padding:30px;
-    background:#fff;
-    box-shadow:#333 1px 1px 5px
+  width: 500px;
+  margin: 0 auto;
+  position: absolute;
+  left: 0;
+  right: 0;
+  top: 20%;
+  padding:30px;
+  background:#fff;
+  box-shadow:#333 1px 1px 5px
 }
 .ver-panel {
-    width:100%;
-    top:10%;
+  width:100%;
+  top:10%;
 }
 .header {
-    border-bottom: 1px solid #ccc
+  border-bottom: 1px solid #ccc
 }
 .header .header-logo {
     background: #ff6501;
@@ -79,26 +96,26 @@ a{
     padding-left:50px;
 }
 .header-logo div.v-title{
-    font-size:11px;
-    color:#aeaeae;
-    line-height: 12px;
-    margin-top:3px;
+  font-size:11px;
+  color:#aeaeae;
+  line-height: 12px;
+  margin-top:3px;
 }
 .header-logo div.p-title{
-    font-size:16px;
-    color:#ff6501;
+  font-size:16px;
+  color:#ff6501;
 }
 .header-logo div.b-title{
-    font-size:24px;
-    color:#ff6501;
+  font-size:24px;
+  color:#ff6501;
 }
 .top-msg{
-    position: fixed;
-    top:10px;
-    width:900px;
-    z-index: 9999;
-    left:50%;
-    margin-left:-450px;
+  position: fixed;
+  top:10px;
+  width:900px;
+  z-index: 9999;
+  left:50%;
+  margin-left:-450px;
 }
 .main {
     position: relative;
@@ -130,45 +147,55 @@ a{
     color: #333
 }
 .main-nav .nav-tabs{
-    border-bottom: none
+  border-bottom: none
 }
 .poj-manage .col-auto{
-    background:#f7f7f9
+  background:#f7f7f9
 }
 .poj-cate {
-    width:58px;
-    margin-right:-1px;
-    margin-top:2px;
+  width:58px;
+  margin-right:-1px;
+  margin-top:2px;
 }
 .poj-cate .nav-pills .nav-link{
-    border-radius: 0;
-    font-size: 24px;
-    color: #007bff
+  border-radius: 0;
+  font-size: 24px;
+  color: #007bff
 }
 .poj-cate .nav-item{
-    position: relative;
+  position: relative;
 }
 .poj-cate .nav-pills .badge{
-    position: absolute;
-    right:5px;
-    top:5px;
+  position: absolute;
+  right:5px;
+  top:5px;
 }
 .poj-cate .nav-pills .nav-link:hover{
-    color:#0056b3
+  color:#0056b3
 }
 .poj-cate .nav-pills .nav-link.active, .nav-pills .show > .nav-link{
-    background-color: #6c757d;
-    color:#fff
+  background-color: #6c757d;
+  color:#fff
+}
+.gl-side.gl-side-lg{
+  width:200px;
+}
+.nav-side .nav-link{
+  padding:.5rem;
+}
+.nav-side .nav-link.active{
+  background:#ddd;
+  color:#333;
 }
 .pm-side{
-    position: fixed;
-    left:0;
-    height:100%;
-    border-right:1px solid #ccc;
-    background: #f7f7f9
+  position: fixed;
+  left:0;
+  height:100%;
+  border-right:1px solid #ccc;
+  background: #f7f7f9
 }
 .pm-content{
-    padding-left:58px
+  padding-left:58px
 }
 .content {
     border-left: 1px solid #ccc;
@@ -176,8 +203,8 @@ a{
     background: #fff
 }
 .toolsbar,.toolsbar-f {
-    background: #f7f7f9;
-    border-bottom: 1px solid #ccc
+  background: #f7f7f9;
+  border-bottom: 1px solid #ccc
 }
 .tools-btn {
     height: 30px;
@@ -187,40 +214,40 @@ a{
     background: #f7f7f9;
 }
 .toolsbar .btn-light {
-    color:#007bff;
-    min-width: 34px;
+  color:#007bff;
+  min-width: 34px;
 }
 .toolsbar .btn-light.disabled {
-    color:#999;
+  color:#999;
 }
 .main-side {
     border-left: 1px solid #ccc;
     overflow-y: hidden;
 }
 .main-data-top,.main-data-full{
-    overflow: hidden;
-    width:100%
+  overflow: hidden;
+  width:100%
 }
 .main-data-top-side{
-    overflow: hidden
+  overflow: hidden
 }
 .main-content.col-lg-8{
-    width:66.666667%
+  width:66.666667%
 }
 .main-content.col-lg-12{
-    width:100%
+  width:100%
 }
 .main-side.col-lg-4{
-    width: 33.333333%;
+  width: 33.333333%;
 }
 .main-side.col-lg-0{
-    width:0%;
+  width:0%;
 }
 .sidebar-middle{
-    height:80px;
+  height:80px;
 }
 .sidebar-bottom,.sidebar-bottom .col-lg-6,.sidebar-bottom .col-lg-12 {
-    height:300px
+  height:300px
 }
 .top-content, .fluid-content {
     overflow: auto;
@@ -244,7 +271,7 @@ a{
     z-index: 999
 }
 .side-tabs .nav-tabs .nav-item {
-    z-index: 999
+  z-index: 999
 }
 .side-tabs .nav-tabs {
     border-bottom: none;
@@ -357,19 +384,9 @@ a{
         transform: translateX(10px);
     }
 }
-.gl-side.gl-side-lg{
-    width:200px;
-}
-.nav-side .nav-link{
-    padding:.5rem;
-}
-.nav-side .nav-link.active{
-    background:#ddd;
-    color:#333;
-}
 .gl-side{
-    border-right:1px solid #ccc;
-    width:120px
+  border-right:1px solid #ccc;
+  width:120px
 }
 .bottom-content .tab-content .main-data-bottom{
     height: 300px;
@@ -383,141 +400,141 @@ a{
     overflow: hidden;
 }
 .tn-nav,.rn-nav{
-    width:30px;
-    height: 100%;
-    border-left:1px solid #dee2e6 ;
+  width:30px;
+  height: 100%;
+  border-left:1px solid #dee2e6 ;
 }
 .tn-nav,.cn-nav{
-    border-right:1px solid #dee2e6 ;
-    border-left:none;
+  border-right:1px solid #dee2e6 ;
+  border-left:none;
 }
 .tn-nav > span{
-    width:20px;
+  width:20px;
 }
 .tn-nav:hover{
-    background:#f7f7f9;
-    cursor: pointer;
+  background:#f7f7f9;
+  cursor: pointer;
 }
 .rn-nav {
-    background: #f7f7f9
+  background: #f7f7f9
 }
 .rn-nav .nav{
-    padding: 0
+  padding: 0
 }
 .rn-nav .nav-tabs {
-    border:none;
-    margin-top:2px;
+  border:none;
+  margin-top:2px;
 }
 .rn-nav .nav-tabs .nav-link{
-    padding:0.4em 0.4em;
-    line-height: 16px
+  padding:0.4em 0.4em;
+  line-height: 16px
 }
 .rn-nav .nav-tabs .nav-link.active {
-    border:none;
-    background-color: #fff;
-    border-left:1px solid #fff;
-    margin-left:-1px;
-    border-top:1px solid #ccc;
-    border-right:1px solid #ccc;
-    border-bottom:1px solid #ccc;
+  border:none;
+  background-color: #fff;
+  border-left:1px solid #fff;
+  margin-left:-1px;
+  border-top:1px solid #ccc;
+  border-right:1px solid #ccc;
+  border-bottom:1px solid #ccc;
 }
 .cn-nav .nav-tabs .nav-link.active {
-    border:none;
-    background-color: #fff;
-    border-right:1px solid #fff;
-    margin-right:-1px;
-    border-top:1px solid #ccc;
-    border-left:1px solid #ccc;
-    border-bottom:1px solid #ccc;
+  border:none;
+  background-color: #fff;
+  border-right:1px solid #fff;
+  margin-right:-1px;
+  border-top:1px solid #ccc;
+  border-left:1px solid #ccc;
+  border-bottom:1px solid #ccc;
 }
 .rn-nav .nav-tabs .nav-link span{
-    display:none;
+  display:none;
 }
 .rn-nav .nav-tabs .nav-link.active span{
-    display: inline-block;
+  display: inline-block;
 }
 .poj-list, .side-content ,.form-view{
     overflow: auto;
 }
 .print-toolsbar{
-    padding:5px
+  padding:5px
 }
 .print-toolsbar .panel {
-    display:inline-block;
-    vertical-align:top
+  display:inline-block;
+  vertical-align:top
 }
 .print-toolsbar .panel .panel-foot{
-    text-align: center;
-    font-size: 12px;
-    padding-bottom:3px;
-    background:#F2F2F2
+  text-align: center;
+  font-size: 12px;
+  padding-bottom:3px;
+  background:#F2F2F2
 }
 .print-list {
-    border-right:1px solid #ccc
+  border-right:1px solid #ccc
 }
 .print-list .form-list {
-    overflow: auto
+  overflow: auto
 }
 .print-list .list-tools{
-    height:50px;
-    padding:10px 0;
-    border-bottom:1px solid #f2f2f2
+  height:50px;
+  padding:10px 0;
+  border-bottom:1px solid #f2f2f2
 }
 .pageContainer {
-    text-align: center
+  text-align: center
 }
 .pageContainer .page{
-    border:9px solid transparent;
-    display: inline-block;
+  border:9px solid transparent;
+  display: inline-block;
 }
 .pageContainer .page img{
-    width:inherit;
-    height: inherit;
+  width:inherit;
+  height: inherit;
 }
 .modal-auto-height {
-    height: 400px;
-    overflow-y: auto;
+  height: 400px;
+  overflow-y: auto;
 }
 .modal-toolbar + .modal-auto-height{
-    height:369px
+  height:369px
 }
 .modal-fixed-height {
-    height: 400px;
-    overflow-y: hidden;
+  height: 400px;
+  overflow-y: hidden;
 }
 .sidebar-tools-bar {
-    background:#fff
+  background:#fff
 }
 .side-search-box{
-    background:#fff;
-    border-bottom:1px solid #ddd
+  background:#fff;
+  border-bottom:1px solid #ddd
 }
 .navbar-crumb span{
-    float:left;
+  float:left;
 }
 .navbar-crumb span.text-truncate{
-    max-width: 200px;
+  max-width: 200px;
 }
 .dropdown-item{
-    color:#007bff
+  color:#007bff
 }
 .dropdown-item:hover{
-    color:#0056b3
+  color:#0056b3
 }
 .dropdown-item.disabled, .dropdown-item:disabled{
-    pointer-events:none
+  pointer-events:none
 }
 .tools-symbol{
-    width:450px
+  width:450px
 }
 .tools-symbol p{
-    margin: 0
+  margin: 0
 }
 .tools-symbol a.btn{
-    font-size: .95rem;
-    width:26px;
-    padding: 0;
-    height:26px;
+  font-size: .95rem;
+  width:26px;
+  padding: 0;
+  height:26px;
 }
 .custom-file-input:lang(zh) ~ .custom-file-label::after {
     content: "浏览";
@@ -550,111 +567,149 @@ a{
     border-color:#000 transparent transparent transparent;
 }
 .box-text-style {
-    font-size: 12px;
-    font-family:"Microsoft YaHei"
+  font-size: 12px;
+  font-family:"Microsoft YaHei"
 }
 .box-text-style p{
-    margin:0 0 2px 0;
+  margin:0 0 2px 0;
 }
 .box-text-style table{
-    width: 100%;
-    text-align: center;
+  width: 100%;
+  text-align: center;
 }
 .box-text-style table th,.box-text-style table td{
-    border:1px solid #fff;
+  border:1px solid #fff;
 }
 
 .box-text-style table p{
-    text-align: left;
+  text-align: left;
 }
 .sys-setting-nav .nav-link{
-    padding:.3rem 1rem;
+  padding:.3rem 1rem;
 }
 /*快捷切换单位工程*/
 .navbar-crumb{
-    position: relative;
+  position: relative;
 }
 .navbar-crumb .f-nav,.navbar-crumb .s-nav{
-    position: absolute;
-    z-index: 999;
-    width: 200px;
-    background:#fff;
-    border: 1px solid rgba(0,0,0,.15);
-    padding: .5rem 0;
+  position: absolute;
+  z-index: 999;
+  width: 200px;
+  background:#fff;
+  border: 1px solid rgba(0,0,0,.15);
+  padding: .5rem 0;
 }
 .navbar-crumb .f-nav{
-    right:50px;
-    top:35px;
+  right:50px;
+  top:35px;
 }
 .navbar-crumb .s-nav{
-    left:200px
+  left:200px
 }
 .navbar-crumb .f-nav li{
-    padding: .25rem 1rem;
-    cursor: default;
+  padding: .25rem 1rem;
+  cursor: default;
 }
 .navbar-crumb .f-nav li.focus{
-    color: #16181b;
-    background-color: #f7f7f9;
+color: #16181b;
+background-color: #f7f7f9;
 }
 .navbar-crumb .f-nav li .s-nav{
-    display: none
+  display: none
 }
 .navbar-crumb .f-nav li.focus .s-nav{
-    display: block
+  display: block
 }
 /*书签颜色*/
 .annotate-color-1{
-    background: #E2F2C5
+  background: #E2F2C5;
+  color: #E2F2C5;
+}
+.annotate-color-1::before{
+  color: #E2F2C5;
+  -webkit-text-stroke:.5px #ced4da;
 }
 .annotate-color-2{
-    background: #F9E2CF
+  background: #F9E2CF;
+  color:#F9E2CF
+}
+.annotate-color-2::before{
+  color: #F9E2CF;
+  -webkit-text-stroke:.5px #ced4da;
 }
 .annotate-color-3{
-    background: #F2EFD9
+  background: #F2EFD9;
+  color:#F2EFD9
+}
+.annotate-color-3::before{
+  color:#F2EFD9;
+  -webkit-text-stroke:.5px #ced4da;
 }
 .annotate-color-4{
-    background: #F5D1DA
+  background: #F5D1DA;
+  color:#F5D1DA
+}
+.annotate-color-4::before{
+  color:#F5D1DA;
+  -webkit-text-stroke:.5px #ced4da;
 }
 .annotate-color-5{
-    background: #E3E3E3
+  background: #E3E3E3;
+  color:#E3E3E3
+}
+.annotate-color-5::before{
+  color:#E3E3E3;
+  -webkit-text-stroke:.5px #ced4da;
 }
 .annotate-color-6{
-    background: #B6F3F2
+  background: #B6F3F2;
+  color:#B6F3F2
+}
+.annotate-color-6::before{
+  color:#B6F3F2;
+  -webkit-text-stroke:.5px #ced4da;
 }
 .annotate-color-7{
-    background: #ECE0F5
+  background: #ECE0F5;
+  color:#ECE0F5
+}
+.annotate-color-7::before{
+  color:#ECE0F5;
+  -webkit-text-stroke:.5px #ced4da;
+}
+.input-group-text.active{
+  color:#666;
 }
 /*宽屏菜单*/
 @media screen and (min-width: 900px) {
-    #fluid-menu{
-    }
-    #min-menu{
-        display: none
-    }
+#fluid-menu{
+}
+#min-menu{
+  display: none
+}
 }
 @media screen and (min-width: 912px) {
-    #share-info{
-        overflow: auto;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        max-width:inherit;
-    }
+#share-info{
+  overflow: auto;
+text-overflow: ellipsis;
+white-space: nowrap;
+max-width:inherit;
+}
 }
 /*窄屏菜单*/
 @media screen and (max-width: 900px) {
-    #fluid-menu{
-        display: none
-    }
-    #min-menu{
+#fluid-menu{
+  display: none
+}
+#min-menu{
 
-    }
+}
 }
 @media screen and (max-width: 1018px) {
-    #share-info{
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        max-width:80px;
-    }
+#share-info{
+  overflow: hidden;
+text-overflow: ellipsis;
+white-space: nowrap;
+max-width:80px;
 }
+}

+ 57 - 11
web/building_saas/main/js/controllers/block_controller.js

@@ -54,6 +54,28 @@ let BlockController = {
         }
         return false;
     },
+    // 恢复删除节点有效性
+    recoverBlockDisabled: function () {
+        if (projectReadOnly) {
+            return true;
+        }
+        const recycle = getLocalCache('project_recycle');
+        if (!recycle) {
+            return true;
+        }
+        const recycleObj = JSON.parse(recycle);
+        const firstData = recycleObj.datas.length ? recycleObj.datas[0] : null;
+        if (!firstData || firstData.projectID !== projectObj.project.ID()) {
+            return true;
+        }
+        const parentID = firstData.sourceType === projectObj.project.Bills.getSourceType() ? firstData.ParentID : firstData.billsItemID;
+        const parent = projectObj.project.mainTree.findNode(parentID);
+        // parentID为-1时,为大项费用
+        if (parentID !== -1 && !parent) {
+            return true;
+        }
+        return false;
+    },
     haveCalcBase : function (node) {
         if(node.data.calcBase ==null||node.data.calcBase ==undefined|| node.data.calcBase == ""){
             return false;
@@ -77,10 +99,9 @@ let BlockController = {
         }
         return null;
     },
-
-    copyBlock:function (selection) {
+    extractBlockData: function (selection) {
         let startTime = +new Date();
-        let blockOjb = {
+        let blockObj = {
             compilationID:projectObj.project.projectInfo.compilation,
             datas:[]
         };
@@ -95,21 +116,30 @@ let BlockController = {
             }
         }
         if(firstNode.sourceType == projectObj.project.Bills.getSourceType()){
-            blockOjb.firstNodeType = firstNode.data.type;
+            // 特殊处理大项费用,因为DXFY在billType中为1,与blockType中的RATION冲突了
+            blockObj.firstNodeType = firstNode.data.type === billType.DXFY ? blockType.DXFY : firstNode.data.type;
         }else if(firstNode.sourceType == projectObj.project.Ration.getSourceType()){
-            blockOjb.firstNodeType = blockType.RATION;
+            blockObj.firstNodeType = blockType.RATION;
         }
-        blockOjb.isFBFX = projectObj.project.Bills.isFBFX(firstNode);
+        blockObj.isFBFX = projectObj.project.Bills.isFBFX(firstNode);
         let ration_glj_Map = _.groupBy(projectObj.project.ration_glj.datas, 'rationID');
         for(let cNode of copyNodes){
-            blockOjb.datas.push(this.getNodeDatas(cNode,ration_glj_Map));
+            blockObj.datas.push(this.getNodeDatas(cNode,ration_glj_Map));
         }
         let getDataTime = +new Date();
         console.log(`复制所用时间——${getDataTime - startTime}`);
-        blockOjb.copyTime = +new Date();//设置复制时间,可以用来做过期处理
-        setLocalCache('project_block',JSON.stringify(blockOjb));
+        blockObj.copyTime = +new Date();//设置复制时间,可以用来做过期处理
         let endTime = +new Date();
         console.log(`复制所用时间——${endTime - startTime}`);
+        return blockObj;
+    },
+    copyBlock:function (selection) {
+        const block = this.extractBlockData(selection);
+        setLocalCache('project_block', JSON.stringify(block));
+    },
+    recycleBlock: function (selection) {
+        const block = this.extractBlockData(selection);
+        setLocalCache('project_recycle', JSON.stringify(block));
     },
     getNodeDatas : function (node,ration_glj_Map) {
         let data = node.data;
@@ -147,7 +177,21 @@ let BlockController = {
         this.confirmPaste(blockData,selected,position);
         //do paste
     },
-
+    // 恢复删除节点
+    recoverBlock: function () {
+        const recycle = JSON.parse(getLocalCache('project_recycle'));
+        const firstData = recycle.datas[0];
+        const parentID = firstData.sourceType === projectObj.project.Bills.getSourceType() ? firstData.ParentID : firstData.billsItemID;
+        // 恢复到父节点最末子项
+        if (parentID !== -1) {
+            const parent = projectObj.project.mainTree.findNode(parentID);
+            this.confirmPaste(recycle, parent, 'sub');
+        } else {
+            // 恢复到最末根节点后项
+            const lastRoot = projectObj.project.mainTree.roots[projectObj.project.mainTree.roots.length - 1];
+            this.confirmPaste(recycle, lastRoot, 'next');
+        }
+    },
     initOptionDiv:function (selected,blockData) {
         let Bills = projectObj.project.Bills;
         if( blockData.firstNodeType == blockType.RATION){//如果剪切板中是复制的定额块
@@ -344,7 +388,9 @@ let BlockController = {
         let sels = projectObj.mainController.sheet.getSelections();
         //设置选中并更新下方显示
         projectObj.mainController.setTreeSelected(firstNode);
-        projectObj.mainController.sheet.setSelection(firstNode.serialNo(), sels[0].col, 1, 1);
+        const serialNo = firstNode.serialNo();
+        projectObj.mainController.sheet.setSelection(serialNo, sels[0].col, 1, 1);
+        projectObj.mainController.sheet.showRow(serialNo, GC.Spread.Sheets.VerticalPosition.center);
         let bottomNodes = [];
         for (let node of newNodes){
             if ((!node.children) || (node.children && node.children.length == 0)){

+ 4 - 0
web/building_saas/main/js/models/bills.js

@@ -710,6 +710,8 @@ var Bills = {
             let includeRootNode=false;
             let parentNodes = [];
             let selection = projectObj.mainSpread.getActiveSheet().getSelections()[0];
+            console.log(`selection`);
+            console.log(selection);
             for(let i =0;i<selection.rowCount;i++){
                 let tem_node = controller.tree.items[selection.row+i];
                 //被行引用的清单(大项费用)不可删除
@@ -771,6 +773,8 @@ var Bills = {
             updateData.user_id = userID;
             $.bootstrapLoading.start();
             CommonAjax.post("/bills/multiDelete", updateData, function () {
+                // 回收删除节点
+                BlockController.recycleBlock(selection);
                 let quantity_detail_datas = project.quantity_detail.datas;
                 let ration_datas = project.Ration.datas;
                 let nodes = controller.tree.nodes;

+ 106 - 70
web/building_saas/main/js/models/calc_base.js

@@ -427,67 +427,79 @@ let cbTools = {
     //@param {Number}baseFee(相关基数金额) {String}name(使用累进计算的基数名称)
     //@return {Number}
     getProgressiveFee: function (baseFee, name) {
-        let progressiveData = calcBase.project.property.progressiveInterval;
+        const progressiveData = calcBase.project.property.progressiveInterval;
         if (!progressiveData) {
             throw '该项目不存在累进区间数据';
         }
-        let matchData = _.find(progressiveData, function (data) {
-            //根据基数名称匹配累进库数据,标准化以免(())等不同导致不匹配
-            return cbAnalyzer.standar(data.name) === cbAnalyzer.standar(name);
-        });
-        if (!matchData) {
-            //return 0;
+        //根据基数名称匹配累进库数据,标准化以免(())等不同导致不匹配
+        const matchProgressiveData = progressiveData.find(item => cbAnalyzer.standar(item.name) === cbAnalyzer.standar(name));
+        if (!matchProgressiveData) {
             throw `计算基数{${name}}不存在累进区间数据`;
         }
-        let progression = matchData.progression;
-        //获取区间中的最小值(0, 10] = 0
-        function getMin(intervalStr) {
-            let str = cbAnalyzer.standar(intervalStr);
-            let match = /\((\d+)?/g.exec(str);
-            return typeof match[1] !== 'undefined' ? parseFloat(match[1]) * 10000 : null; //后台数据单位为万元,这里转为为元
-        }
-        //获取区间中的最大值(0, 10] = 10
-        function getMax(intervalStr) {
-            let str = cbAnalyzer.standar(intervalStr);
-            let match = /[\,,,](\d+)?/g.exec(str);
-            return typeof match[1] !== 'undefined' ? parseFloat(match[1]) * 10000 : null
-        }
-        //将累进区间进行排序
-        progression.sort(function (a, b) {
-           let aV = getMin(a.interval),
-               bV = getMin(b.interval);
-           if (aV > bV) {
-               return 1;
-           } else if (aV < bV) {
-               return -1;
-           }
-           return 0;
+        // 将原始数据转换成方便处理的数据:[{feeRate: xx, min: 0, max: 200, minOpr: '(', maxOpr: ']'}]
+        const progression = matchProgressiveData.progression.map(item => {
+            // item.interval内容: eg (0,200]、[300,500) [1000,+)....
+            const interval = cbAnalyzer.standar(item.interval);
+            // ( => 大于 [ => 大于等于 ) => 小于 ] => 小于等于
+            const minReg = /([\(\[])(\d+)/;
+            const minMatch = minReg.exec(interval);
+            if (!minMatch || !minMatch[1] || !minMatch[2]) {
+                throw `计算基数{${name}}累进区间数据错误`;
+            }
+            const minOpr = minMatch[1];
+            // 后台数据单位为万元,这里转为为元
+            const min = parseFloat(minMatch[2]) * 10000;
+            const maxReg = /[\,,]([\d\+]+)([\)\]])/;
+            const maxMatch = maxReg.exec(interval);
+            if (!maxMatch || !maxMatch[1] || !maxMatch[2]) {
+                throw `计算基数{${name}}累进区间数据错误`;
+            }
+            const max = maxMatch[1] === '+' ? 'infinity' : parseFloat(maxMatch[1]) * 10000;
+            const maxOpr = maxMatch[2];
+            return {
+                feeRate: item.feeRate,
+                min,
+                minOpr,
+                max,
+                maxOpr
+            }
         });
-        //累进计算
-        let fee = 0;
-        //找到所在区间
-        let within = _.find(progression, function (data) {
-            let min = getMin(data.interval),
-                max = getMax(data.interval);
-            return min !== null && baseFee > min  && (max !== null && baseFee <= max || max === null);
+        progression.sort((a, b) => a.min - b.min);
+        // 基数所在区间
+        const withinData = progression.find(item => {
+            const oprMiddle = item.max === 'infinity' ? '+' : '';
+            const oprLink = item.minOpr + oprMiddle + item.maxOpr;
+            switch (oprLink) {
+                case '()':
+                    return baseFee > item.min && baseFee < item.max;
+                case '(]':
+                    return baseFee > item.min && baseFee <= item.max;
+                case '[)':
+                    return baseFee >= item.min && baseFee < item.max;
+                case '[]':
+                    return baseFee >= item.min && baseFee <= item.max;
+                case '(+)':
+                case '(+]':
+                    return baseFee > item.min;
+                case '[+)':
+                case '[+]':
+                    return baseFee >= item.min;
+                default:
+                    return false;
+            }
         });
-        if (!within) {
+        if (!withinData) {
             return 0;
         }
+        // 累进计算
+        let fee = 0;
         //累进之前的区间
-        for (let i = 0; i < progression.indexOf(within); i++) {
-            let perData = progression[i],
-                min = getMin(perData.interval),
-                max = getMax(perData.interval);
-            if (min !== null && max !== null) {
-                fee += (max - min) * perData.feeRate * 0.01;
-            }
+        for (let i = 0; i < progression.indexOf(withinData); i++) {
+            const perData = progression[i];
+            fee += (perData.max - perData.min) * perData.feeRate * 0.01;
         }
         //累进所在区间
-        let min = getMin(within.interval);
-        if (min !== null) {
-            fee += (baseFee - min) * within.feeRate * 0.01;
-        }
+        fee += (baseFee - withinData.min) * withinData.feeRate * 0.01;
         return fee.toDecimal(decimalObj.bills.totalPrice);
     },
     //获取清单100章下的节点(只需要找最底层的,排除了底层,父项金额即排除了子项)
@@ -718,107 +730,125 @@ let baseFigureMap = {
     'budget': {
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '定额建筑安装工程费(不含定额设备购置费及专项费用)': {
-            base: 'DEJZAZGCFBHSBZX', fixedFlag: null,
+            base: 'DEJZAZGCFBHSBZX',
+            fixedFlag: null,
             filter: [fixedFlag.SPECIAL_COST, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         '定额建筑安装工程费(其中定额设备购置费按40%计)': {
-            base: 'DEJZAZGCSBSS', fixedFlag: null,
+            base: 'DEJZAZGCSBSS',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“安全生产费”
         '建筑安装工程费(不含安全生产费)': {
-            base: 'JZAZGCFBHSC', fixedFlag: null,
+            base: 'JZAZGCFBHSC',
+            fixedFlag: null,
             filter: [fixedFlag.SAFE_COST],
             pick: true
         },
         //只允许固定类别是“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '建筑安装工程费(不含设备费)': {
-            base: 'JZAZGCFBHSB', fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
+            base: 'JZAZGCFBHSB',
+            fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许非固定类别是“建筑安装工程费”下的清单引用
         '建筑安装工程费': {
-            base: 'JZAZGCF', fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
+            base: 'JZAZGCF',
+            fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
             filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
             pick: false
         },
         //只允许非固定类别是“建筑安装工程费”、非固定类别是“土地使用及拆迁补偿费”下的清单引用
         '土地使用及拆迁补偿费': {
-            base: 'TDSYJCQBCF', fixedFlag: fixedFlag.LAND_USED_DEMOLITION,
+            base: 'TDSYJCQBCF',
+            fixedFlag: fixedFlag.LAND_USED_DEMOLITION,
             filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION],
             pick: false,
         },
         //只允许非固定类别是“建筑安装工程费”、非固定类别是“土地使用及拆迁补偿费”、非固定类别是“养护工程其他费”下的清单引用
         '养护工程其他费': {
-            base: 'YHGCQTF', fixedFlag: fixedFlag.MAINTENANCE_EXPENSES,
+            base: 'YHGCQTF',
+            fixedFlag: fixedFlag.MAINTENANCE_EXPENSES,
             filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: false
         },
         //只允许非固定类别是“建筑安装工程费”、非固定类别是“土地使用及拆迁补偿费”、非固定类别是“养护工程其他费”、非固定类别是“预备费”下的清单引用。
         '预备费': {
-            base: 'YBF', fixedFlag: fixedFlag.BUDGET_FEE,
+            base: 'YBF',
+            fixedFlag: fixedFlag.BUDGET_FEE,
             filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES, fixedFlag.BUDGET_FEE],
             pick: false
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '施工场地建设费': {
-            base: 'SGCDJSF', fixedFlag: null,
+            base: 'SGCDJSF',
+            fixedFlag: null,
             filter: [fixedFlag.SPECIAL_COST, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '养护单位(业主)管理费': {
-            base: 'YHDWYZGLF', fixedFlag: null,
+            base: 'YHDWYZGLF',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '信息化费': {
-            base: 'XXHF', fixedFlag: null,
+            base: 'XXHF',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '路线工程监理费': {
-            base: 'LXGCJLF', fixedFlag: null,
+            base: 'LXGCJLF',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '独立桥梁隧道工程监理费': {
-            base: 'QLSDGCJLF', fixedFlag: null,
+            base: 'QLSDGCJLF',
+            fixedFlag: null,
             filter: [ fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '设计文件审查费': {
-            base: 'SJWJSCF', fixedFlag: null,
+            base: 'SJWJSCF',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '路线勘察设计费': {
-            base: 'LXKCSJF', fixedFlag: null,
+            base: 'LXKCSJF',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“专项费用”、“土地使用及拆迁补偿费“、“养护工程其他费”下的清单使用
         '独立桥梁隧道维修加固勘察设计费': {
-            base: 'QLSDKCSJF', fixedFlag: null,
+            base: 'QLSDKCSJF',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         '招标代理及标底(最高投标限价)编制费': {
-            base: 'ZBDLJBDBZF', fixedFlag: null,
+            base: 'ZBDLJBDBZF',
+            fixedFlag: null,
             filter: [fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
             pick: true
         },
         //只允许固定类别是“价差预备费”的清单使用
         '价差预备费': {
-            base: 'JCYBF', fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
+            base: 'JCYBF',
+            fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
             filter: [fixedFlag.SPREAD_BUDGET_FEE],
             pick: true
         }
@@ -829,12 +859,16 @@ let baseFigureMap = {
     * */
     'boq': {
         //仅允许用于固定类别是“第100章至700章清单”以外的清单
-        '各章清单合计': {base: 'GZQDHJ', fixedFlag: fixedFlag.ONE_SEVEN_BILLS,
+        '各章清单合计': {
+            base: 'GZQDHJ',
+            fixedFlag: fixedFlag.ONE_SEVEN_BILLS,
             filter: [fixedFlag.ONE_SEVEN_BILLS],
             pick: false
         },
         //仅允许用于固定类别是“第100章至700章清单”以外的清单
-        '专项暂定合计': {base: 'ZXZDHJ', fixedFlag: null,
+        '专项暂定合计': {
+            base: 'ZXZDHJ',
+            fixedFlag: null,
             filter: [fixedFlag.ONE_SEVEN_BILLS],
             pick: false
         },
@@ -843,7 +877,9 @@ let baseFigureMap = {
         *  因此{100章以外合计}不设置关联的清单固定行
         * */
         //仅允许用于固定类别为“100章清单”引用
-        '100章以外清单合计': {base: 'YBZYHQDHJ', fixedFlag: null,
+        '100章以外清单合计': {
+            base: 'YBZYHQDHJ',
+            fixedFlag: null,
             filter: [fixedFlag.ONE_HUNDRED_BILLS],
             pick: true
         },

+ 23 - 8
web/building_saas/main/js/models/calc_program.js

@@ -93,6 +93,19 @@ let calcTools = {
     isTechMeasure:function(treeNode){
        return projectObj.project.Bills.isTechMeasure(treeNode)
     },
+    isInheritFrom:function(treeNode, flag){
+        let rst = false;
+        let curNode = treeNode;
+        while (curNode){
+            if (curNode.data && curNode.data.flagsIndex && curNode.data.flagsIndex.fixed &&
+                curNode.data.flagsIndex.fixed.flag == flag){
+                rst = true;
+                break;
+            }
+            curNode = curNode.parent;
+        };
+        return rst;
+    },
     getChildrenFormulaNodes: function (self, allFormulaNodesArr, parentNodes){       // 获取结点parentNodes下有公式的子结点
         let nodes = [];
         for (let pn of parentNodes){
@@ -1179,8 +1192,8 @@ let analyzer = {
             for (let base of arrBase){
                 let baseName = base.slice(1, -1);
                 if (!rationCalcBases[baseName]){
-                    analyzer.error = `定额基数${hintBox.font('[' +baseName + ']')}定义!`;
-                    // hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}定义!`, 1);
+                    analyzer.error = `定额基数${hintBox.font('[' +baseName + ']')}定义!`;
+                    // hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}定义!`, 1);
                     return false;
                 }
             };
@@ -1394,7 +1407,7 @@ let executeObj = {
             return calcTools.marketPriceToBase(me.treeNode, baseName, isTender)
         else{
             if (!rationCalcBases[baseName]){
-                hintBox.infoBox('系统提示', '定额基数“' + baseName + '”定义,计算错误。 (模板 ' + me.template.ID + ',规则 ' + me.tempCalcItem.ID +')', 1);
+                hintBox.infoBox('系统提示', '定额基数“' + baseName + '”定义,计算错误。 (模板 ' + me.template.ID + ',规则 ' + me.tempCalcItem.ID +')', 1);
                 return 0;
             }
             else
@@ -1779,12 +1792,14 @@ class CalcProgram {
                 calcTools.checkFeeField(treeNode, ftObj);
 
                 // 数量、金额时,同步定额建安费
-                let ftObj2 = {
-                    fieldName: 'rationCommon',
-                    unitFee: uf,
-                    totalFee: tf
+                if (calcTools.isInheritFrom(treeNode, 1)){
+                    let ftObj2 = {
+                        fieldName: 'rationCommon',
+                        unitFee: uf,
+                        totalFee: tf
+                    };
+                    calcTools.checkFeeField(treeNode, ftObj2);
                 };
-                calcTools.checkFeeField(treeNode, ftObj2);
             }
 
             treeNode.data.calcTemplate = {"calcItems": []};

+ 7 - 3
web/building_saas/main/js/models/fee_rate.js

@@ -227,10 +227,14 @@ var FeeRate = {
                     calcProgramObj.refreshCalcProgram(node, 3);
                 }
             }
-            project.calcProgram.calcAllNodesAndSave(calcAllType.catAll);
-            project.markUpdateProject({projectID:project.ID(),feeRateID:this.getActivateFeeRateFileID()},"feeRate",function () {
-                socket.emit('feeRateChangeNotify', {projectID:project.ID(),feeRateID:me.getActivateFeeRateFileID(),userID:userID});
+            project.calcProgram.calcAllNodesAndSave(calcAllType.catAll,function () {
+                $.bootstrapLoading.start();
+                project.markUpdateProject({projectID:project.ID(),feeRateID:me.getActivateFeeRateFileID()},"feeRate",function () {
+                    $.bootstrapLoading.end();
+                    socket.emit('feeRateChangeNotify', {projectID:project.ID(),feeRateID:me.getActivateFeeRateFileID(),userID:userID});
+                });
             });
+
         };
 
 

+ 7 - 2
web/building_saas/main/js/models/main_consts.js

@@ -266,7 +266,11 @@ const fixedFlag = {
     //安全生产费
     SAFE_COST:27,
     //100章清单
-    ONE_HUNDRED_BILLS: 28
+    ONE_HUNDRED_BILLS: 28,
+    // 一二三部分合计
+    ONE_TO_THREE_TOTAL: 29,
+    // 前期工作费
+    PRELIMINARY_WORK: 30,
 };
 
 const gljKeyArray =['code','name','specs','unit','type'];
@@ -347,7 +351,8 @@ const blockType ={
     FB:2,//分部
     FX:3,//分项
     BILL:4,//清单
-    BX:5//补项
+    BX:5,//补项
+    DXFY:6//大项费用
 };
 
 const filterType = {

+ 1 - 0
web/building_saas/main/js/views/calc_program_view.js

@@ -52,6 +52,7 @@ let calcProgramObj = {
                 break;
             case 2:
                 projectObj.project.calcProgram.innerCalc(treeNode, []);
+                projectObj.project.calcProgram.rationMap = null;
                 delete treeNode.changed;
                 break;
             case 3:

+ 6 - 2
web/building_saas/main/js/views/fee_rate_view.js

@@ -409,6 +409,7 @@ var feeRateObject={
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMainFeeRateRangeChanged);
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.EditStarting, function (e,args) {
             let me =feeRateObject;
+            if($.bootstrapLoading.isLoading())  args.cancel = true;
             if(!me.mainFeeRateEditChecking(args.row,args.col)){
                 args.cancel = true;
             }
@@ -635,8 +636,11 @@ var feeRateObject={
                 }
                 subRateObject.showSubRateData();
                 me.showMainFeeRateData();
-                feerateInfo.length > 0 ?feeRate.onFeeRatesChange(feerateInfo):'';
-                $.bootstrapLoading.end();
+                if(feerateInfo.length > 0){
+                    feeRate.onFeeRatesChange(feerateInfo);
+                }else {
+                    $.bootstrapLoading.end();
+                }
             })
         }
         function getRateByStep(ltValue,total,share,step) { //min值 ,计算值的总区间, 区间中占比,步长--后端重选标准也要用到

+ 1 - 1
web/building_saas/main/js/views/glj_view.js

@@ -959,7 +959,7 @@ var gljOprObj = {
         }
     },
     showLibGLJSheetData: function () {
-        this.gljLibSheetData = _.sortBy(this.gljLibSheetData, 'code');
+        //this.gljLibSheetData = _.sortBy(this.gljLibSheetData, 'code');
         sheetCommonObj.showData(this.gljLibSheet, this.gljLibSheetSetting, this.gljLibSheetData, gljOprObj.distTypeTree);
         this.gljLibSheet.setRowCount(this.gljLibSheetData.length);
     },

+ 6 - 1
web/building_saas/main/js/views/glj_view_contextMenu.js

@@ -377,7 +377,12 @@ function getGLJData(actionType) {
     $('#actionType').val(actionType);
     $.bootstrapLoading.start();
     projectObj.project.ration_glj.getGLJData(function (result) {
-        gljOprObj.treeData =  result.datas.treeData;
+        // 目前只有浙江2015需要处理
+        if (gljOprObj.sortSelectViewGLJ) {
+            gljOprObj.sortSelectViewGLJ(result.datas.stdGLJ);
+            gljOprObj.sortSelectViewGLJ(result.datas.complementaryGLJs);
+        }
+        gljOprObj.treeData = result.datas.treeData;
         //zTreeHelper.createTree(result.datas.treeData, gljOprObj.gljTreeSetting, "gljTree", gljOprObj);
         gljOprObj.initClassTree('std', gljOprObj.treeData.std);
         gljOprObj.stdGLJ=result.datas.stdGLJ;

+ 10 - 0
web/building_saas/main/js/views/project_view.js

@@ -1501,6 +1501,16 @@ var projectObj = {
                         BlockController.pasteBlock(project.mainTree.selected);
                     }
                 },
+                "recoverDeletedNodes": {
+                    name: '恢复删除节点',
+                    icon: 'fa-undo',
+                    disabled: function (){
+                        return BlockController.recoverBlockDisabled();
+                    },
+                    callback: function () {
+                        BlockController.recoverBlock();
+                    }
+                },
                 "editEngineer": {
                     name: '编辑工程内容',
                     icon: 'fa-edit',

+ 21 - 4
web/building_saas/main/js/views/sub_fee_rate_views.js

@@ -5,6 +5,7 @@
 var subRateObject={
     views:null,
     datas:null,
+    timeStamp:null,
     valueMap:null,
     canEdit:true,
     subRateSpread:null,
@@ -46,6 +47,7 @@ var subRateObject={
             this.subRateSheet = this.subRateSpread.getSheet(0);
             sheetCommonObj.initSheet(this.subRateSheet, this.subRateSetting, 30);
             this.subRateSheet.bind(GC.Spread.Sheets.Events.SelectionChanged, this.onSubRateSelectChanged);
+            this.subRateSheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onSubRateEditStarting);
             this.subRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onSubRateValueChange);
             //this.subRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, me.onSheetValueChange);
             this.subRateSheet.name('subRateSheet');
@@ -118,6 +120,10 @@ var subRateObject={
             $('#'+item.ID).val(selectvalue);
         })
     },
+    onSubRateEditStarting :function(e,info){
+        if($.bootstrapLoading.isLoading())  info.cancel = true;
+    },
+
     onSubRateValueChange:function (e,info) {
         let me = subRateObject, subList=null;
         let value = info.newValue;
@@ -128,11 +134,9 @@ var subRateObject={
                 value = scMathUtil.roundForObj(checkResult,getDecimal("feeRate"));
             }else {
                 alert('当前输入的数据类型不正确,请重新输入。');
-                me.showSubRateData();
-                return;
+                return me.showSubRateData();
             }
         }
-
         if(subRate.isSub == true){//是树节点的子节点,计算父节点的值
             let parentRate = _.find(me.datas,{"ID":subRate.ParentID});//找到父节点
             if(parentRate){
@@ -152,7 +156,20 @@ var subRateObject={
                 t.value = value
             }
         }
-        feeRateObject.setRateFromSub(subRate,value,subList,info.newValue);
+        if(me.timeStamp = null){
+            me.timeStamp =  +new Date()
+            feeRateObject.setRateFromSub(subRate,value,subList,info.newValue);
+        }else {
+            let now = +new Date();
+            if(now - me.timeStamp < 500){
+                setTimeout(function () {
+                    feeRateObject.setRateFromSub(subRate,value,subList,info.newValue);
+                },500)
+            }else {
+                feeRateObject.setRateFromSub(subRate,value,subList,info.newValue);
+            }
+            me.timeStamp = now;
+        }
     },
 
     destorySpreadView:function () {

+ 1 - 1
web/building_saas/pm/html/project-management.html

@@ -393,7 +393,7 @@
                         <label>文件夹</label>
                         <input type="text" class="form-control" placeholder="输入文件夹名称" id="folder-name">
                         <span class="form-text text-danger" id="folder-name-info" style="display: none;">已存在 “建筑工程1”</span>
-                        <span class="form-text text-muted">Smartcost目前最多支持3层文件夹。</span>
+                        <span class="form-text text-muted">目前最多支持3层文件夹。</span>
                     </div>
                 </form>
             </div>

+ 249 - 0
web/over_write/js/neimeng_2019.js

@@ -0,0 +1,249 @@
+/**
+ * Created by CSL on 2019/09/23.  内蒙计算程序、基数 等覆盖。
+ */
+
+let isNM2019 = true;
+
+function overwriteRationCalcBases (){
+    if (typeof rationCalcBases == 'undefined') return;
+    for (let key in rationCalcBases) delete rationCalcBases[key];
+
+    rationCalcBases['人工费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.LABOUR], priceTypes.ptMarketPrice, isTender);
+    };
+    rationCalcBases['材料费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, baseMaterialTypes, priceTypes.ptMarketPrice, isTender);
+    };
+    rationCalcBases['施工机械使用费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, baseMachineTypes, priceTypes.ptMarketPrice, isTender);
+    };
+    rationCalcBases['施工机械人工费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.MACHINE_LABOUR], priceTypes.ptDiffPrice, isTender);
+    };
+    rationCalcBases['设备购置费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.EQUIPMENT], priceTypes.ptMarketPrice, isTender);
+    };
+
+    rationCalcBases['定额人工费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.LABOUR], priceTypes.ptBasePrice, isTender);
+    };
+    rationCalcBases['定额材料费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, baseMaterialTypes, priceTypes.ptBasePrice, isTender);
+    };
+    rationCalcBases['定额施工机械使用费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, baseMachineTypes, priceTypes.ptBasePrice, isTender);
+    };
+    rationCalcBases['定额商品砼费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.COMMERCIAL_CONCRETE, gljType.COMMERCIAL_MORTAR], priceTypes.ptBasePrice, isTender);
+    };
+    rationCalcBases['定额设备费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.EQUIPMENT], priceTypes.ptBasePrice, isTender);
+    };
+    rationCalcBases['定额外购砼构件费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.PURCHASE_COMPONENT], priceTypes.ptBasePrice, isTender);
+    };
+    rationCalcBases['定额绿化苗木费'] = function (node, isTender) {
+        return calcTools.rationBaseFee(node, [gljType.GREEN_SEEDLING], priceTypes.ptBasePrice, isTender);
+    };
+};
+
+(function overwriteFeeTypes() {
+    if (typeof cpFeeTypes == 'undefined') return;
+    cpFeeTypes = [
+        {type: 'labour', name: '人工费'},
+        {type: 'material', name: '材料费'},
+        {type: 'machine', name: '施工机械使用费'},
+        {type: 'equipment', name: '设备购置费'},
+        {type: 'direct', name: '直接费'},
+
+        {type: 'rLabour', name: '定额人工费'},
+        {type: 'rMaterial', name: '定额材料费'},
+        {type: 'rMachine', name: '定额施工机械使用费'},
+        {type: 'rEquipment', name: '定额设备购置费'},
+        {type: 'rDirect', name: '定额直接费'},
+
+        {type: 'measure', name: '措施费'},
+        {type: 'manage', name: '企业管理费'},
+        {type: 'force', name: '规费'},
+        {type: 'profit', name: '利润'},
+        {type: 'tax', name: '税金'},
+        {type: 'common', name: '建安费'},
+        {type: 'rCommon', name: '定额建安费'},
+        {type: 'safeProduce', name: '安全生产费'}
+    ];
+})();
+
+// 清单基数,工程量清单的基数没有变化,只修改预算的
+if (typeof baseFigureMap !== 'undefined' && baseFigureMap.budget) {
+    baseFigureMap.budget = {
+        // 清单固定类别是“建筑安装工程费”的以外部分可显示
+        '定额建筑安装工程费(定额设备购置费按40%计)': {
+            base: 'DEJZAZGCFSBSS',
+            fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
+            pick: false,
+        },
+        // 清单固定类别是“建筑安装工程费”的以外部分可显示
+        '建筑安装工程费(不含设备费)': {
+            base: 'JZAZGCFBHSB',
+            fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
+            pick: false,
+        },
+        // 清单固定类别是“建筑安装工程费”的以外部分可显示
+        '建筑安装工程费': {
+            base: 'JZAZGCF',
+            fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
+            pick: false,
+        },
+        // “建筑安装工程费”、“土地使用及拆迁补偿费”以外部分可显示
+        '土地使用及拆迁补偿费': {
+            base: 'TDSYJCQBCF',
+            fixedFlag: fixedFlag.LAND_USED_DEMOLITION,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION],
+            pick: false,
+        },
+        // “建筑安装工程费”、“土地使用及拆迁补偿费”、“养护工程其他费用”以外部分可显示
+        '养护工程其他费用': {
+            base: 'YHGCQTFY',
+            fixedFlag: fixedFlag.MAINTENANCE_EXPENSES,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES],
+            pick: false,
+        },
+        // “建筑安装工程费”、“土地使用及拆迁补偿费”、“养护工程其他费用”以外部分可显示
+        '预备费': {
+            base: 'YBF',
+            fixedFlag: fixedFlag.BUDGET_FEE,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.LAND_USED_DEMOLITION, fixedFlag.MAINTENANCE_EXPENSES, fixedFlag.BUDGET_FEE],
+            pick: false,
+        },
+        // 仅在清单固定类别是“养护单位项目管理费”的清单显示
+        '养护单位项目管理费': {
+            base: 'YHDWXMGLF',
+            fixedFlag: null,
+            filter: [fixedFlag.MAINTENANCE_MANAGENENT_FEE],
+            pick: true,
+        },
+        // 仅在清单固定类别是“信息化费”的清单显示
+        '信息化费': {
+            base: 'XXHF',
+            fixedFlag: null,
+            filter: [fixedFlag.INFORMATIZATION_FEE],
+            pick: true,
+        },
+        // 仅在清单固定类别是“工程监理费”的清单显示
+        '工程监理费': {
+            base: 'GCJLF',
+            fixedFlag: null,
+            filter: [fixedFlag.ENGINEERING_SUP_FEE],
+            pick: true,
+        },
+        // 仅在清单固定类别是“设计文件审查费”的清单显示
+        '设计文件审查费': {
+            base: 'SJWJSCF',
+            fixedFlag: null,
+            filter: [fixedFlag.DOCUMENT_REVIEW_FEE],
+            pick: true,
+        },
+        '前期工作费': {
+            base: 'QQGZF',
+            fixedFlag: null,
+            filter: [fixedFlag.PRELIMINARY_WORK],
+            pick: true,
+        },
+        '价差预备费': {
+            base: 'JCYBF',
+            fixedFlag: null,
+            filter: [fixedFlag.SPREAD_BUDGET_FEE],
+            pick: true,
+        },
+    }
+}
+
+// 清单基数,工程量清单的基数没有变化,只修改预算的
+if (typeof baseFigureTemplate !== 'undefined' && baseFigureTemplate.budget) {
+    baseFigureTemplate.budget = {
+        // 定额建筑安装工程费(定额设备购置费按40%计):取清单固定类别是“建筑安装工程”的定额建安费,其中定额设备购置费按40%计算
+        DEJZAZGCFSBSS(tender) {
+            const feeField = 'rCommon';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            const deductFlags = [fixedFlag.EQUIPMENT_ACQUISITION_FEE];
+            //建安费扣除定额设备购置费
+            const afterDeductFee = cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, deductFlags, `${feeField}.${subFeeField}`);
+            //定额设备购置费
+            const equipmentAcFee = cbTools.getBillsFee(deductFlags[0], feeField, subFeeField);
+            return (afterDeductFee + equipmentAcFee * 0.4).toDecimal(decimalObj.bills.totalPrice);
+        },
+        // 建筑安装工程费(不含设备费):取清单固定类别是“建筑安装工程”的金额,但要扣除清单固定类别是“设备购置费”的金额
+        JZAZGCFBHSB(tender) {
+            const fullFeeField = tender ? 'common.tenderTotalFee' : 'common.totalFee';
+            const deductFlags = [fixedFlag.EQUIPMENT_ACQUISITION_FEE];
+            //建安费扣除设备费
+            return cbTools.getFeeWithDeduction(fixedFlag.CONSTRUCTION_INSTALL_FEE, deductFlags, fullFeeField).toDecimal(decimalObj.bills.totalPrice);
+        },
+        // 建筑安装工程费:取清单固定类别是“建筑安装工程”的金额
+        JZAZGCF(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, feeField, subFeeField);
+        },
+        // 土地使用及拆迁补偿费:取清单固定类别是“土地使用及拆迁补偿费”的金额
+        TDSYJCQBCF(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(fixedFlag.LAND_USED_DEMOLITION, feeField, subFeeField);
+        },
+        // 养护工程其他费用:取清单固定类别是“养护工程其他费用”的金额
+        YHGCQTFY(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(fixedFlag.MAINTENANCE_EXPENSES, feeField, subFeeField);
+        },
+        // 预备费:取清单固定类别是“预备费”的金额
+        YBF(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(fixedFlag.BUDGET_FEE, feeField, subFeeField);
+        },
+        // 养护单位项目管理费:以累进办法计算,计算基数为“定额建筑安装工程费(定额设备购置费按40%计)
+        YHDWXMGLF(tender) {
+            const baseFee = this['DEJZAZGCFSBSS'](tender);
+            return cbTools.getProgressiveFee(baseFee, '养护单位项目管理费');
+        },
+        // 信息化费:以累进办法计算,计算基数为“定额建筑安装工程费(定额设备购置费按40%计)”
+        XXHF(tender) {
+            const baseFee = this['DEJZAZGCFSBSS'](tender);
+            return cbTools.getProgressiveFee(baseFee, '信息化费');
+        },
+        // 工程监理费:以累进办法计算,计算基数为“定额建筑安装工程费(定额设备购置费按40%计)
+        GCJLF(tender) {
+            const baseFee = this['DEJZAZGCFSBSS'](tender);
+            return cbTools.getProgressiveFee(baseFee, '工程监理费');
+        },
+        // 设计文件审查费:以累进办法计算,计算基数为“定额建筑安装工程费(定额设备购置费按40%计)”;设计文件审查费不足3000元的,按3000元计算
+        SJWJSCF(tender) {
+            const baseFee = this['DEJZAZGCFSBSS'](tender);
+            const fee = cbTools.getProgressiveFee(baseFee, '设计文件审查费');
+            return fee > 0 && fee < 3000 ? 3000 : fee;
+        },
+        // 前期工作费:以累进办法计算,计算基数为“定额建筑安装工程费(定额设备购置费按40%计)
+        QQGZF(tender) {
+            const baseFee = this['DEJZAZGCFSBSS'](tender);
+            return cbTools.getProgressiveFee(baseFee, '前期工作费');
+        },
+        // 价差预备费
+        JCYBF(tender) {
+            //建筑安装工程费作为基数
+            const installFee = this['JZAZGCF'](tender);
+            //年造价增涨
+            const costGrowthRate = calcBase.project.property.costGrowthRate ?
+                calcBase.project.property.costGrowthRate : 0;
+            //增涨计费年限
+            const growthPeriod = projectObj.project.property.growthPeriod ?
+                calcBase.project.property.growthPeriod : 0;
+            //= P * [(1+i)^(n-1) -1]
+            return (installFee * (Math.pow(1 + costGrowthRate, growthPeriod - 1) - 1)).toDecimal(decimalObj.bills.totalPrice);
+        },
+    };
+}

+ 174 - 2
web/over_write/js/zhejiang_2005.js

@@ -1,5 +1,5 @@
 /**
- * Created by CSL on 2019/09/11.  江西计算程序、基数 等覆盖。
+ * Created by CSL on 2019/09/11.  江计算程序、基数 等覆盖。
  */
 
 let isZJ2005 = true;
@@ -16,7 +16,7 @@ function overwriteRationCalcBases (taxType){
     rationCalcBases['材料费'] = function (node, isTender) {
         return calcTools.rationBaseFee(node, baseMaterialTypes, priceTypes.ptMarketPrice, isTender);
     };
-    rationCalcBases['施工机械使用费'] = function (node, isTender) {
+    rationCalcBases['施工机械使用费'] = function (node, isTender) {
         return calcTools.rationBaseFee(node, baseMachineTypes, priceTypes.ptMarketPrice, isTender);
     };
 };
@@ -39,10 +39,182 @@ function overwriteRationCalcBases (taxType){
     ];
 })();
 
+// 清单基数,工程量清单的基数没有变化,只修改预算的
+if (typeof baseFigureMap !== 'undefined' && baseFigureMap.budget) {
+    baseFigureMap.budget = {
+        // 除清单固定类别是“建筑安装工程费”的以外部分可显示
+        '公路养护工程费': {
+            base: 'GLYHGCF',
+            fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
+            pick: false,
+        },
+        // 除清单固定类别是“建筑安装工程费”、“设备购置费”的以外部分可显示
+        '设备购置费用': {
+            base: 'SBGZFY',
+            fixedFlag: fixedFlag.EQUIPMENT_ACQUISITION_FEE,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.EQUIPMENT_ACQUISITION_FEE],
+            pick: false,
+        },
+        // 除清单固定类别是“建筑安装工程费”、“设备购置费”、“养护工程其他费用”的以外部分可显示
+        '公路养护工程其他费用': {
+            base: 'GLYHGCQTFY',
+            fixedFlag: fixedFlag.MAINTENANCE_EXPENSES,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.EQUIPMENT_ACQUISITION_FEE, fixedFlag.MAINTENANCE_EXPENSES],
+            pick: false,
+        },
+        // 只有清单固定类别是“养护工程其他费用”部分可显示
+        '养护工程管理经费': {
+            base: 'YHGCGLJF',
+            fixedFlag: null,
+            filter: [fixedFlag.MAINTENANCE_EXPENSES],
+            pick: true,
+        },
+        // 除清单固定类别是“建筑安装工程费”、“设备购置费”、“养护工程其他费用”、“一二三部分合计”的以外部分可显示
+        '一二三部分合计': {
+            base: 'YESBFHJ',
+            fixedFlag: fixedFlag.ONE_TO_THREE_TOTAL,
+            filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE, fixedFlag.EQUIPMENT_ACQUISITION_FEE, fixedFlag.MAINTENANCE_EXPENSES, fixedFlag.ONE_TO_THREE_TOTAL],
+            pick: false,
+        },
+        // 只有清单固定类别是“预备费”部分可显示
+        '工程造价增涨预留费': {
+            base: 'GCZJZZYLF',
+            fixedFlag: null,
+            filter: [fixedFlag.BUDGET_FEE],
+            pick: true,
 
+        }
+    }
+}
+// 清单基数,工程量清单的基数没有变化,只修改预算的
+if (typeof baseFigureTemplate !== 'undefined' && baseFigureTemplate.budget) {
+    baseFigureTemplate.budget = {
+        // 公路养护工程费:取清单固定类别是“建筑安装工程费”的金额
+        GLYHGCF(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(calcBase.fixedFlag.CONSTRUCTION_INSTALL_FEE, feeField, subFeeField);
+        },
+        // 设备购置费用:取清单固定类别是“设备购置费”的金额
+        SBGZFY(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(calcBase.fixedFlag.EQUIPMENT_ACQUISITION_FEE, feeField, subFeeField);
+        },
+        // 公路养护工程其他费用:取清单固定类别是“养护工程其他费用”的金额。
+        GLYHGCQTFY(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(calcBase.fixedFlag.MAINTENANCE_EXPENSES, feeField, subFeeField);
+        },
+        // 养护工程管理经费:取清单固定类别是“建筑安装工程费”金额为基数,采用累进办法计算
+        YHGCGLJF(tender) {
+            const baseFee = this['GLYHGCF'](tender);
+            return cbTools.getProgressiveFee(baseFee, '养护工程管理费');
+        },
+        // 一二三部分合计:取清单固定类别是“一二三部分合计”的金额
+        YESBFHJ(tender) {
+            const feeField = 'common';
+            const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+            return cbTools.getBillsFee(calcBase.fixedFlag.ONE_TO_THREE_TOTAL, feeField, subFeeField);
+        },
+        // 工程造价增涨预留费:以{公路养护工程费}为基数,= P * [(1+i)^(n-1) -1]
+        // P:公路养护工程费总额(元)
+        // i:年造价增长率(%)(项目属性已有字段)
+        // N:增涨计费年限(项目属性已有字段)
+        GCZJZZYLF(tender) {
+            const baseFee = this['GLYHGCF'](tender);
+            //年造价增涨
+            const costGrowthRate = calcBase.project.property.costGrowthRate
+                ? calcBase.project.property.costGrowthRate
+                : 0;
+            //增涨计费年限
+            const growthPeriod = projectObj.project.property.growthPeriod
+                ? calcBase.project.property.growthPeriod
+                : 0;
+            return (baseFee * (Math.pow(1 + costGrowthRate, growthPeriod - 1) - 1)).toDecimal(decimalObj.bills.totalPrice);
+        }
+    };
+}
+
+if (typeof gljOprObj !== 'undefined') {
+    // 添加、替换工料机界面工料机排序
+    gljOprObj.sortSelectViewGLJ = function (data) {
+        // 工料机编码:按“-”前的数值排序
+        const reg = /[^-]+/;
+        data.sort((a, b) => {
+            const orgCodeA = a.code;
+            const orgCodeB = b.code;
+            const regCodeA = orgCodeA.match(reg);
+            const regCodeB = orgCodeB.match(reg);
+            const compareCodeA = regCodeA
+                ? +regCodeA[0]
+                    ? +regCodeA[0]
+                    : regCodeA[0]
+                : orgCodeA;
+            const compareCodeB = regCodeB
+                ? +regCodeB[0]
+                    ? +regCodeB[0]
+                    : regCodeB
+                : orgCodeB;
+            return isNaN(compareCodeA) && isNaN(compareCodeB)
+                ? compareCodeA.localeCompare(compareCodeB)
+                : compareCodeA - compareCodeB;
+        });
+        // 工料机类型排序:人工、机上人工、混凝土、砂浆、配合比、普通材料、商品混凝土、商品砂浆、外购砼构件、绿化苗木、机械台班、机械组成物、设备。
+        const TypeMap = {
+            1: 1,
+            303: 2,
+            202: 3,
+            203: 4,
+            204: 5,
+            201: 6,
+            205: 7,
+            206: 8,
+            208: 9,
+            209: 10,
+            301: 11,
+            302: 12,
+            5: 13,
+        };
+        data.sort((a, b) => {
+            const typeA = TypeMap[a.gljType];
+            const typeB = TypeMap[b.gljType];
+            return typeA - typeB;
+        });
+    }
+
+}
 
+if(typeof gljUtil !== 'undefined'){
+    gljUtil.getCodeSortMath = getCodeSortMath
+}
 
 
+if(typeof module !== 'undefined'){
+    let _= require('lodash');
+
+    module.exports = {
+        sortRationGLJ: function(list){
+            list = _.sortByAll(list, [function (item) {
+                return getMainType(item.gljType?item.gljType:item.type);
+            }, getCodeSortMath()]);
+            return list;
+
+            function getMainType(type) {
+                let str = type + "";
+                return parseInt(str.substr(0,1));
+            }
+        }
+    };
+}
 
+function getCodeSortMath() {
+    return function (item) {
+        let arr = item.code.split('-');
+        return parseInt(arr[0])
+    }
+}