Explorar o código

Merge branch '1.0.0_online' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost into 1.0.0_online

chenshilong %!s(int64=6) %!d(string=hai) anos
pai
achega
6213a261e2

+ 1 - 1
modules/all_models/ration_template.js

@@ -23,4 +23,4 @@ let ration_template =  new Schema({
     },{ _id: false })]
 },{versionKey:false});
 
-mongoose.model('ration_template', ration_template);
+mongoose.model('ration_template', ration_template,"ration_template");

+ 11 - 2
modules/bills_lib/models/bills_lib_interfaces.js

@@ -4,6 +4,7 @@
 let mongoose = require('mongoose');
 let counter = require("../../../public/counter/counter");
 let async = require("async");
+let _ = require("lodash");
 let StdBillsLib = mongoose.model('std_bills_lib_list');
 let Bills = mongoose.model('std_bills_lib_bills');
 let JobContent = mongoose.model('std_bills_lib_jobContent');
@@ -3069,10 +3070,12 @@ billsLibDao.prototype.getStdBillsByCode = async function (data, callback) {
             //设置项目特征
             let itemCharacters = await ItemCharacter.find({billsLibId: data.billsLibId, deleted: false}, '-_id');
             bills._doc.itemCharacter = [];
+            bills.items = _.sortBy(bills.items,"serialNo");//排序
             if(itemCharacters && bills.items){
                 for(let item of bills.items){
                     let itemData = findData(item, 'id', itemCharacters);
                     if(itemData){
+                        itemData._doc.serialNo = item.serialNo;
                         bills._doc.itemCharacter.push(itemData);
                     }
                 }
@@ -3081,20 +3084,26 @@ billsLibDao.prototype.getStdBillsByCode = async function (data, callback) {
             //设置工作内容
             let jobContents = await JobContent.find({billsLibId: data.billsLibId, deleted: false}, '-_id');
             bills._doc.jobContent = [];
+            bills.jobs = _.sortBy(bills.jobs,"serialNo");//排序
             if(jobContents && bills.jobs){
                 for(let job of bills.jobs){
                     let jobData = findData(job, 'id', jobContents);
                     jobData.isChecked = true;
+                    jobData._doc.serialNo = job.serialNo;
                     bills._doc.jobContent.push(jobData);
                 }
             }
             bills._doc.jobContentText = MergeData(bills._doc.jobContent);
         }
-        callback(0, '', bills);
-
+        if(callback){
+            callback(0, '', bills);
+        }else {
+            return bills;
+        }
     }
     catch(err){
         callback(1, err, null);
+        return null;
     }
 };
 billsLibDao.prototype.getStdBillsByCodet = function (data, callback) {

+ 30 - 0
modules/main/controllers/ration_controller.js

@@ -4,6 +4,8 @@
 var rationData = require('../models/ration');
 var ration_glj_facade = require('../../ration_glj/facade/ration_glj_facade');
 var ration_facade = require('../facade/ration_facade');
+let bill_facade = require('../facade/bill_facade');
+let project_facade = require("../facade/project_facade");
 let logger = require("../../../logs/log_helper").logger;
 let controller = {
     insertGLJAsRation:async function (req){
@@ -47,9 +49,37 @@ let controller = {
         return await ration_facade.getDefaultProgramID(data);
 
 
+    },
+    //应用定额关联子目
+    applyTemplate:async function(req){
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let rationResult = [],billsResult = [],updateDatas =[];
+        //先生成新定额
+        if(data.rations.create.length > 0){
+            rationResult = await ration_facade.addMultiRation(data.rations.create,req.session.sessionCompilation);
+        }
+        //再生成清单
+        if(data.bills.create.length > 0){
+            billsResult =  await bill_facade.createNewBills(data.bills.create)
+        }
+        //整理更新的数据,调用一个方法更新
+        updateDatas.push(data.ration_template);
+        if(data.rations.update.length > 0)  prepareUpdateNodes(data.rations.update,updateDatas,"ration");
+        if(data.bills.update.length > 0)  prepareUpdateNodes(data.bills.update,updateDatas,"bills");
+        await project_facade.updateNodes(updateDatas);
+        return {rationResult:rationResult,billsResult:billsResult,updateDatas:updateDatas};
     }
 };
 
+function prepareUpdateNodes(datas,nodes,type) {
+    for(let d of datas){
+        nodes.push({type:type,data:d});
+    }
+
+}
+
+
 
 //统一回调函数
 let callback = function(req, res, err, message, data){

+ 28 - 1
modules/main/facade/bill_facade.js

@@ -16,6 +16,9 @@ let ration_coe_Model = mongoose.model('ration_coe');
 let ration_installation_Model = mongoose.model('ration_installation');
 let ration_template_Model = mongoose.model('ration_template');
 let bill_Model = require('../models/bills').model;
+let billsLibDao = require("../../bills_lib/models/bills_lib_interfaces");
+
+
 import GLJController from "../../glj/controllers/glj_controller";
 
 import GLJListModel from '../../glj/models/glj_list_model';
@@ -82,7 +85,31 @@ module.exports={
         resultMap.ration_gljs = rationsAndRationGLJ.new_ration_gljs;
         resultMap.gljData = projectGLJ.data;
         return resultMap;
-    }
+    },
+    createNewBills:async function(newDatas){
+        // billsLibDao.getStdBillsByCode  从这里取数据
+        let results = [];
+        for(let bills of newDatas){
+            let stdB = await  billsLibDao.getStdBillsByCode({billsLibId:bills.billsLibId,code:bills.billsLocation});
+            if(stdB){
+                stdB = JSON.parse(JSON.stringify(stdB));
+                if(!bills.unit && /\//.test(stdB.unit)){
+                    bills.unit = stdB.unit.split(/\//)[0];
+                }
+                //处理项目特征和工作内容,现在默认都添加到项目特征列中
+                stdB.itemCharacterText = "[项目特征]\n[工作内容]\n"+stdB.jobContentText;
+                stdB.jobContentText="";
+                bills =  _.merge(stdB,bills);
+            }
+            delete bills.billsLocation;
+            results.push(bills);
+        }
+        if(results.length > 0){
+            await bill_Model.create(results);
+        }
+        return results;
+
+    },
 };
 
 async function pasteOtherData(data) {

+ 5 - 0
modules/main/facade/project_facade.js

@@ -11,6 +11,7 @@ let bill_model = require('../models/bills');
 let consts = require('../models/project_consts');
 let projectConsts = consts.projectConst;
 let ration_glj_model = mongoose.model('ration_glj');
+let rationTemplateModel = mongoose.model('ration_template');
 let project_glj_model = mongoose.model('glj_list');
 let ration_glj_facade = require("../../ration_glj/facade/ration_glj_facade");
 const uuidV1 = require('uuid/v1');
@@ -132,6 +133,7 @@ async function updateNodes(datas){
     let rationGLJTasks = [];
     let projectGLJTasks = [];
     let projectTasks = [];
+    let rationTemplateTasks = [];
     let asyncTasks = [];
     for(let type in nodeGroups){
         for(let node of nodeGroups[type]){
@@ -145,6 +147,8 @@ async function updateNodes(datas){
                 projectGLJTasks.push(getTask(node,'id'));
             }else if(type == projectConsts.PROJECT){
                 projectTasks.push(getTask(node));
+            }else if(type == projectConsts.RATION_TEMPLATE){
+                rationTemplateTasks.push(getTask(node))
             }
 
         }
@@ -154,6 +158,7 @@ async function updateNodes(datas){
     rationGLJTasks.length>0?asyncTasks.push(ration_glj_model.bulkWrite(rationGLJTasks)):"";
     projectGLJTasks.length>0?asyncTasks.push(project_glj_model.bulkWrite(projectGLJTasks)):"";
     projectTasks.length>0?asyncTasks.push(projectsModel.bulkWrite(projectTasks)):"";
+    rationTemplateTasks.length>0?asyncTasks.push(rationTemplateModel.bulkWrite(rationTemplateTasks)):"";
     return  asyncTasks.length>0?await Promise.all(asyncTasks):"";
 
     function getTask(node,idFiled = 'ID') {

+ 3 - 3
modules/main/facade/ration_facade.js

@@ -263,12 +263,12 @@ async function addRationTemplate(std,newRation) {
                 fxID:"",
                 quantity:"0",
                 coe:"0"
-            }
+            };
             template.code = tem.code;
             template.name = tem.name;
             template.type = tem.type;
-            template.unit = tem.unit &&_.isString(tem.unit)?tem.unit.replace(/^\d+/,""):"";
-            template.billsLocation = template.billsLocation
+            template.unit = tem.unit;
+            template.billsLocation = tem.billsLocation;
             templateList.push(template)
         }
     }

+ 1 - 0
modules/main/routes/ration_route.js

@@ -15,5 +15,6 @@ module.exports = function (app) {
     rationRouter.post('/addMultiRation', rationController.action);
     rationRouter.post('/getSameSectionRations', rationController.action);
     rationRouter.post('/getDefaultProgramID', rationController.action);
+    rationRouter.post('/applyTemplate', rationController.action);
     app.use('/ration', rationRouter);
 };

+ 7 - 0
web/building_saas/css/custom.css

@@ -269,3 +269,10 @@ legend.legend{
 input.text-right{
     text-align: right;
 }
+
+.cus-width{
+    width: 100%;
+}
+.more{
+    padding-left:.25rem!important
+}

+ 6 - 6
web/building_saas/main/html/main.html

@@ -157,7 +157,7 @@
                               <a class="nav-link px-1 right-nav-link" href="javascript:void(0)" id="stdRationTab" relaPanel="#de">定额库</a>
                           </li>
                           <li class="nav-item dropdown">
-                              <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">更多</a>
+                              <!--<a class="nav-link dropdown-toggle more" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">更多</a>-->
                               <div class="dropdown-menu">
                                   <a class="dropdown-item  right-nav-link"  href="javascript:void(0)" id = 'locateTab' relaPanel="#locate">查找定位</a>
                                  <!-- <a class="dropdown-item" data-toggle="tab" href="#sqpz" role="tab">书签批注</a>-->
@@ -213,7 +213,7 @@
                                   <li class="nav-item" id = "TZJNR_div">
                                       <a class="nav-link sub-item" id="linkTZJNR" data-toggle="tab" href="#subSpread" role="tab">特征及内容</a>
                                   </li>
-                                  <!--<li class="nav-item" id="MBZM_div">
+                                <!--  <li class="nav-item" id="MBZM_div">
                                       <a class="nav-link sub-item" id="linkMBZM" data-toggle="tab" href="#subSpread" role="tab">模板子目</a>
                                   </li>-->
                               </ul>
@@ -241,18 +241,18 @@
                                               <div class="col-12" style="background: #F1F1F1;">
                                                   <div class="row" style="border-bottom:1px solid #ccc">
                                                       <label class="col-auto col-form-label col-form-label-sm">提取位置</label>
-                                                      <div class="col-2">
-                                                          <select class="form-control  form-control-sm" id="createLocation">
+                                                      <div class="">
+                                                          <select class="form-control  form-control-sm" id="createLocation" style="width: auto">
                                                               <option value="1">模板子目分别放在措施项目下</option>
                                                               <option value="2">模板子目分别放在分部分项下</option>
                                                               <option value="3">模板子目分别放在对应混凝土子目下</option>
                                                           </select>
                                                       </div>
                                                       <div class="col-1">
-                                                          <button class=" btn btn-primary btn-sm form-control" type="button" id="apply_mbzm">应用</button>
+                                                          <button class=" btn btn-primary btn-sm cus-width" type="button" id="apply_mbzm">应用</button>
                                                       </div>
                                                       <div class="col-1">
-                                                          <button class=" btn btn-primary btn-sm form-control" type="button" id="next_mbzm">下一条</button>
+                                                          <button class=" btn btn-primary btn-sm cus-width" type="button" id="next_mbzm">下一条</button>
                                                       </div>
                                                   </div>
                                               </div>

+ 20 - 15
web/building_saas/main/js/models/bills.js

@@ -406,7 +406,7 @@ var Bills = {
                 }
                 return s;
             }
-            for (i = 0; i <= matchs.length; i++) {
+            for (let i = 0; i <= matchs.length; i++) {
                 let formatCode = stdCode + format(i+1);
                 if (matchs.indexOf(formatCode) === -1) {
                     return formatCode;
@@ -840,18 +840,33 @@ var Bills = {
         bills.prototype.getAllBXs = function () {
           return _.filter(this.datas,{"type":billType.BX});
         };
-        bills.prototype.getNewInstallBillData = function (code,billID,feeType) {
+
+        bills.prototype.getAutoParentNode = function (type) {//取需自动生成清单的父节点
             let controller = projectObj.mainController;
             let parentNode;
-            if(feeType == '措施费用'){
+            if(type == '措施费用'){
                 parentNode = this.getTechNode();
             }else {
                 let rootNode = this.getFBFXNode(controller);
-                   parentNode =getLeaveBill(rootNode.source);
-                if(parentNode.data.type == billType.FX){//如果是分项的话,取父节点
+                parentNode =getLeaveBill(rootNode.source);
+                if(parentNode.data.type == billType.FX||parentNode.data.type == billType.BX){//如果是分项或补项的话,取父节点
                     parentNode = parentNode.parent;
                 }
             }
+            return parentNode;
+
+            function getLeaveBill(node) {
+                if(node.children.length>0){
+                    return getLeaveBill(node.children[node.children.length-1]);
+                }else {
+                    return node;
+                }
+            }
+        };
+
+
+        bills.prototype.getNewInstallBillData = function (code,billID,feeType) {
+            let parentNode = this.getAutoParentNode(feeType);
             if(!billID){
                 billID = uuid.v1();
             }
@@ -866,16 +881,6 @@ var Bills = {
                 quantity:'1'
             };
             return data;
-
-            function getLeaveBill(node) {
-                if(node.children.length>0){
-                    return getLeaveBill(node.children[node.children.length-1]);
-                }else {
-                    return node;
-                }
-            }
-
-
         };
 
         return new bills(project);

+ 42 - 0
web/building_saas/main/js/models/project.js

@@ -408,6 +408,48 @@ var PROJECT = {
             })
         };
 
+        project.prototype.updateNodesCache =function (datas) {
+            let refreshNode = [];
+            for(let d of datas){
+                let temObj = null;
+                if(d.type == ModuleNames.bills || d.type == ModuleNames.ration){//如果是树节点类型,直接取树节点更新
+                    let temNode = this.mainTree.getNodeByID(d.data.ID);
+                    if(temNode){
+                        temObj = temNode.data;
+                        refreshNode.push(temNode);
+                    }
+                }else {//其它类型,更新datas
+                    temObj = _.find(this[d.type].datas,{"ID":d.data.ID});
+                }
+                if(temObj){
+                    console.log(temObj);
+                    for(let key in d.data){
+                        if(key == 'ID' || key == 'id'){
+                            continue;
+                        }
+                        this.setValue(temObj,key,d.data[key])
+                    }
+                    console.log(temObj);
+                }
+            }
+        };
+        project.prototype.setValue=function (obj,key,value) {
+            let keyArray = key.split('.');
+            t_set(obj,value,keyArray,0);
+            function t_set(obj,value,arr,index) {
+                let nextIndex = index + 1;
+                let tkey = arr[index];
+                if(nextIndex < arr.length){
+                    if(obj[tkey]==undefined){
+                        obj[tkey] = {};
+                    }
+                    t_set(obj[tkey],value,arr,nextIndex)
+                }else if(nextIndex == arr.length){
+                    obj[tkey] = value;
+                }
+            }
+
+        }
         project.prototype.updateEvalproject = function (evalProject,data,callback){
             let programID = null;
             if(evalProject ==1){//当打勾估价项目选项后,该定额取费专业读取计算程序名称为“估价项目”的计算程序,且为只读状态

+ 3 - 1
web/building_saas/main/js/views/installation_fee_view.js

@@ -769,7 +769,7 @@ let installationFeeObj={
                 name : n.data.name
             };
             //project.mainTree.selected.data.calcBase&&project.mainTree.selected.data.calcBase!=""
-            if(n.data.type == billType.FX){//分项才能选
+            if(n.data.type == billType.FX||n.data.type == billType.BX){//分项/补项才能选
                 temData.canSelect = true;
             }else if(n.data.type == billType.BILL){//如果是清单类型,则是叶子节点并且没有使用基数计算的清单
                 if (n.children.length==0&&!(n.data.calcBase&&n.data.calcBase!="")){
@@ -800,6 +800,8 @@ let installationFeeObj={
                 this.updateRationInstallPosition(pobj.recode);
             }else if(from =='modifyFeeRuleSheet'){
                 this.updateModifyFeeRulePosition(pobj.recode);
+            }else if(from == "ration_template"){
+                mbzm_obj.updatePosition(pobj.recode);
             }
         }
         $("#calc_position").modal('hide');

+ 353 - 7
web/building_saas/main/js/views/mbzm_view.js

@@ -6,26 +6,34 @@ let mbzm_obj={
     spread:null,
     nodeChanged:false,
     datas:[],
+    locateMap:{
+      INMEASURE:1,
+      INFBFX:2,
+      AFTERRATION:3
+    },
     setting:{
         header: [
             {headerName: "编码", headerWidth: 130, dataCode: "code", dataType: "String", formatter: "@"},
             {headerName: "模板类别", headerWidth: 260, dataCode: "name", dataType: "String", hAlign: "left"},
             {headerName: "系数", headerWidth: 65, dataCode: "coe", dataType: "Number",validator:"number"},
-            {headerName: "单位", headerWidth: 45, dataCode: "unit", dataType: "String", hAlign: "center"},
+            {headerName: "单位", headerWidth: 45, dataCode: "unit", dataType: "String", hAlign: "center",getText:'forUnit'},
             {headerName: "工程量", headerWidth: 65, dataCode: "quantity", dataType: "Number",validator:"number"},
             {headerName: "关联类别", headerWidth: 100, dataCode: "type", dataType: "String"},
             {headerName: "清单位置", headerWidth: 200, dataCode: "position", hAlign: "left", dataType: "String",cellType:'selectButton',getText:'forPosition'},
         ],
         view: {
-            lockColumns:["code","name","unit","type","fxID"],
+            lockColumns:["code","name","unit","type"],
             rowHeaderWidth:25
         },
         getText:{
             forPosition:function (item) {
                 let createL =  $('#createLocation').val();
-                if(createL == 1) return  mbzm_obj.getDisplayText(item.billID,item.billsLocation);
-                if(createL == 2) return  mbzm_obj.getDisplayText(item.fxID,"");
+                if(createL == mbzm_obj.locateMap.INMEASURE) return  mbzm_obj.getDisplayText(item.billID,item.billsLocation);
+                if(createL == mbzm_obj.locateMap.INFBFX) return  mbzm_obj.getDisplayText(item.fxID,"");
                 return ""
+            },
+            forUnit:function (item) {//这里显示的单位是去掉定额单位前面的数字的结果
+               return item.unit &&_.isString(item.unit)?item.unit.replace(/^\d+/,""):""
             }
         }
     },
@@ -63,8 +71,8 @@ let mbzm_obj={
         let selected = node?node:projectObj.project.mainTree.selected;
         if(this.nodeChanged == true){//选中的行改变了才做初始化,刷新当前缓存, 在project_view 中treeSelectedChanged方法里设置
             let datas = [];
-            $("#createLocation").val(1);//初始化
-            if(selected&&selected.sourceType == "ration"){
+            $("#createLocation").val(this.locateMap.INMEASURE);//初始化
+            if(selected&&selected.sourceType == ModuleNames.ration){
                 let ration = selected.data;
                 let  template = projectObj.project.ration_template.getTemplateByRationID(ration.ID);
                 if(template) {
@@ -106,13 +114,351 @@ let mbzm_obj={
         }
         recode[dataCode] = value;
         me.refreshSheetData();
+    },
+    updatePosition:function (recode) {
+        let selection = this.sheet.getSelections()[0];
+        let selectedItem  =(this.datas[selection.row]);
+        let updateField = $("#createLocation").val()==this.locateMap.INMEASURE?"billID":"fxID";
+        if(selectedItem[updateField] == recode.ID) return;
+        selectedItem[updateField] = recode.ID;
+        if($("#createLocation").val()==this.locateMap.INMEASURE)selectedItem.billsLocation = recode.code;
+        this.refreshSheetData();
+    },
+    applyTemplate:function () {//应用清单模板
+        let selected = projectObj.project.mainTree.selected;
+        let template = projectObj.project.ration_template.getTemplateByRationID(selected.data.ID);
+        let createLocation = $("#createLocation").val();
+        let rations = {update:[],create:[]},bills={update:[],create:[]};
+        if(this.datas.length <= 0) return;
+        for(let d of this.datas){
+            if(gljUtil.isDef(d.quantity)&& parseFloat(d.quantity)>0){
+                if(this.positionChecking(createLocation,d) == false){
+                    alert(`请选择${d.code}生成的清单位置`);
+                    return;
+                }
+                this.getNodeUpdateData(d,selected.data.ID,createLocation,rations,bills);
+            }
+        }
+        let ration_template={type:ModuleNames.ration_template,data:{ID:template.ID, createLocation:createLocation, templateList:this.datas}};
+        let data = {
+            ration_template:ration_template,
+            rations:rations,
+            bills:bills
+        };
+
+        console.log(data);
+        $.bootstrapLoading.start();
+        CommonAjax.post('/ration/applyTemplate',data,function (result) {
+            $.bootstrapLoading.end();
+            let refreshNodes = projectObj.project.updateNodesCache(result.updateDatas);//更新要update的前端缓存,并返回要刷新的树节点
+            //对于新插入的清单:
+            if(result.billsResult.length > 0){
+
+            }
+            //对于新插入的定额
+
+
+            console.log(result);
+        })
+
+    },
+    positionChecking(type,data){//这个要之后再测试一下
+        let validate = true;
+        if(type == mbzm_obj.locateMap.INMEASURE){
+            if(!_.isEmpty(data.billID)){
+                let node = projectObj.project.mainTree.getNodeByID(data.billID);
+                if(!node) validate = false;//ID有值,但是找不到,说明清单已经被删除
+            }else if(_.isEmpty(data.billsLocation)){
+                validate = false
+            }
+        }else {
+            if(_.isEmpty(data.fxID)) {
+                validate = false;
+            }else {
+                let node = projectObj.project.mainTree.getNodeByID(data.fxID);
+                if(!node) validate = false;//ID有值,但是找不到,说明分项已经被删除
+            }
+        }
+        return validate
+    },
+    getNodeUpdateData:function(data,referenceRationID,type,rations,bills){
+        let quantity = this.getQuantity(data);//工程量要经过转换
+        let mainRation = projectObj.project.mainTree.getNodeByID(referenceRationID);
+        let billsID="";
+        //先检查要更新的定额是否已经存在
+        let ration = this.getExistRation(data,referenceRationID,type);
+        if(ration) {//如果存在,则比较清耗量、工程量表达式是否一致
+            let tem =  this.getRationData(ration,data,quantity);//取更新信息
+            if(tem){//如果不一致,则需要更新
+                rations.update.push(tem);
+            }
+            //在定额存在的情况下,不用往下执行了
+            return;
+        }
+        //定额不存在的情况下
+        if(type == mbzm_obj.locateMap.AFTERRATION) {//如果是生成在主定额后面的位置
+            this.createNewRationAfterMain(data,mainRation,quantity,rations);
+        }
+        if(type == mbzm_obj.locateMap.INMEASURE){//生成在措施项目下
+            this.createNewRationInMeasure(data,mainRation,quantity,rations,bills);
+        }else {
+            this.createNewRationInFBFX(data,mainRation,quantity,rations,bills);
+        }
+
+        /*[
+            {
+                type:'ration',
+                data:{
+                    projectID:1605,
+                    ID:"7b962fb0-1131-11e8-b3da-af725dadd7ae",
+                    name:'testRation'
+                }
+            },
+            {
+                type:'bills',
+                data:{
+                    projectID:1605,
+                    ID:"af9f0081-1127-11e8-99a8-2fc02230b6e7",
+                    name:'安全文明施工专项费用123'
+                }
+            }
+        ]*/
+    },
+    getRationData:function (ration,data,quantity) {
+        let tem = {};
+        if (ration.quantity + "" != quantity) tem.quantity = quantity;
+        if (gljUtil.isDef(data.coe) && data.coe != "0") tem.quantityEXP = "MBGCL";
+        if(!_.isEmpty(tem)) {
+            tem.projectID = ration.projectID;
+            tem.ID = ration.ID;
+            return tem;
+        }
+        return null;
+    },
+    createNewRationAfterMain:function (data,mainRation,quantity,rations) {
+        //生成新的定额
+        let newID =  uuid.v1();
+        let serialNo = mainRation.data.serialNo+1;
+        //如果已经有正要生成的定额,则取这个序号再加1
+        if(rations.create.length > 0){
+            serialNo = rations.create[rations.create.length -1].newData.serialNo + 1
+        }
+        let n_ration = this.createNewRationData(data,newID,mainRation.data.referenceRationID,mainRation.data.billsItemID,serialNo,quantity,mainRation.data.libID);
+        rations.create.push(n_ration);
+        //处理其它兄弟节点的序号
+        let br = projectObj.project.Ration.getBillsSortRation();
+        for(let i = mainRation.data.serialNo;i<br.length;i++){
+            if(rations.update.length > 0){//如果update列表中有数据,要更新那里的序列号
+               let u =  _.find(rations.update,{'ID':br[i].ID});
+               if(u){
+                   u.serialNo += 1;
+                   continue;
+               }
+            }
+            rations.update.push({ID:br[i].ID,projectID:br[i].projectID,serialNo:br[i].serialNo+1})
+        }
+    },
+    createNewRationInMeasure:function (data,mainRation,quantity,rations,bills) {
+        let controller = projectObj.mainController;
+        let billsID="";
+        if(!_.isEmpty(data.billID)&&projectObj.project.mainTree.getNodeByID(data.billID)){
+            billsID = data.billID;
+        }else {//剩下的就是没找到的
+            let rootNode = projectObj.project.Bills.getMeasureNode(controller);
+            let leaveNodes = projectObj.mainController.tree.getLeavesNodes(rootNode.source);
+            for(let n of leaveNodes){
+                if (!(n.data.calcBase&&n.data.calcBase!="")&& n.data.code&&(n.data.code ==data.billsLocation||n.data.code.indexOf(data.billsLocation) != -1)){//没有使用基数计算的清单
+                    billsID = n.data.ID;
+                    break;
+                }
+            }
+            if(billsID == ""){//还是没有找到的情况下,先查找是不是已经生成过了
+                if(bills.create.length > 0){
+                    let t_b = _.find(bills.create,{"billsLocation":data.billsLocation});
+                    if(t_b) billsID = t_b.ID;
+                }
+            }
+            if(billsID == ""){//也没有生成过的情况下,要自动生成清单
+                let parentNode = projectObj.project.Bills.getAutoParentNode("措施费用");
+                billsID = uuid.v1();
+                let newBill = {
+                    ID:billsID,
+                    projectID: parseInt(projectObj.project.ID()),
+                    ParentID:parentNode.data.ID,
+                    NextSiblingID:-1,
+                    code:projectObj.project.Bills.newFormatCode(data.billsLocation),
+                    billsLibId:projectInfoObj.projectInfo.engineeringInfo.bill_lib[0].id,//projectInfoObj.projectInfo.engineeringInfo.billsGuidance_lib
+                    billsLocation : data.billsLocation//这个是用来在后端查找清单信息
+                };
+                let existB = projectObj.project.Bills.sameStdCodeBillsData(data.billsLocation);//对于多单位的清单
+                if (existB) {
+                    newBill.unit = existB.unit;
+                }
+                //将这个节点的上一节点的NextSiblingID设置为这个新清单
+                //先看有没有刚生成的清单,有的话直接修改最后一个清单的NextSiblingID即可
+                let lastIndex = this.getLastIndex(bills.create,"ParentID",parentNode.data.ID);
+                if(bills.create.length > 0 && lastIndex!=-1){
+                    bills.create[lastIndex].NextSiblingID = newBill.ID;
+                }else if(parentNode.children.length > 0){//如果新生的没有找到的话,查看父节点下是否有子节点
+                    let pre = parentNode.children[parentNode.children.length-1];
+                    bills.update.push({ projectID:newBill.projectID,ID:pre.data.ID, NextSiblingID:newBill.ID});
+                }
+                bills.create.push(newBill);
+            }
+        }
+        //生成定额
+        let newID =  uuid.v1();
+        let serialNo = 1;
+        serialNo =  this.checkAndGetSerialNo(serialNo,billsID,rations);
+        //先查看刚生成的定额中有没有相同父清单,有的话取最后的一个序列号加1
+        let n_ration = this.createNewRationData(data,newID,mainRation.data.ID,billsID,serialNo,quantity,mainRation.data.libID);
+        rations.create.push(n_ration);
+    },
+    createNewRationInFBFX:function (data,mainRation,quantity,rations,bills) {
+        let billsID = "";
+        let parentNode = projectObj.project.mainTree.getNodeByID(data.fxID);
+        //分部分项这里,如果没选择位置,或者选择后又删除了,是无法到这一步的,所以不用像生成在清单那里做很多检查
+        if(!_.isEmpty(data.fxID)&&parentNode){
+            billsID = data.fxID;
+        }
+        if(billsID !=""){
+            //生成定额
+            let newID =  uuid.v1();
+            let serialNo = 1;
+             serialNo =  this.checkAndGetSerialNo(serialNo,billsID,rations);
+            let n_ration = this.createNewRationData(data,newID,mainRation.data.ID,billsID,serialNo,quantity,mainRation.data.libID,true);
+            rations.create.push(n_ration);
+        }
+    },
+    getLastIndex:function (arrays,key,value) {
+        let index = -1;
+        for (let i = 0;i<arrays.length;i++) {
+            if(arrays[i][key] == value){
+                index = i;
+            }
+        }
+        return index;
+    },
+    checkAndGetSerialNo:function (sNo,billsID,rations) {
+        let serialNo = sNo;
+        //先查看刚生成的定额中有没有相同父清单,有的话取最后的一个序列号加1
+        let last_ration = this.getLastBrotherNewRation(billsID,rations.create);
+        if(last_ration){
+            serialNo = last_ration.serialNo +1;
+        }else {
+            let parentBillsNode = projectObj.project.mainTree.getNodeByID(billsID);
+            if(parentBillsNode && parentBillsNode.children.length > 0){//如果能找到则说明已经存在的清单
+                serialNo = parentBillsNode.children[parentBillsNode.children.length - 1].data.serialNo + 1
+            }
+        }
+        return serialNo
+    },
+    getLastBrotherNewRation:function(billsItemID,rations){
+        let newData = null;
+        for(let tem of rations){
+            if(tem.newData.billsItemID == billsItemID)  newData = tem.newData;
+        }
+        return newData;
+    },
+    createNewRationData:function (data,newID,referenceRationID,billsID,serialNo,quantity,libID,isFBFX) {
+        let newData = projectObj.project.Ration.getTempRationData(newID,billsID,serialNo,rationType.ration);
+        newData.referenceRationID = referenceRationID;
+        newData.quantity = quantity;
+        newData.quantityEXP = gljUtil.isDef(data.coe) && data.coe != "0"?"MBGCL":quantity+"";
+        let temRation = this.getDefaultRationCreateData(newData,data.code,libID,isFBFX);
+        return temRation;
+    },
+    getDefaultRationCreateData:function(newData,code,libID,isFBFX){
+        let itemQuery = {userID: userID, rationRepId: libID, code: code};
+        let needInstall = false;
+        if(projectObj.project.isInstall()) {//如果是安装工程,要看需不需要生成安装增加费
+            needInstall = isFBFX;//在分部分项插入的定额才需要定额安装增加费
+        }
+        return{itemQuery:itemQuery,newData:newData,defaultLibID: rationLibObj.getDefaultStdRationLibID(),calQuantity:false,brUpdate:[],needInstall:needInstall}
+    },
+    getQuantity:function (data) {//取最新的消耗量,需经过转换
+        if(data.unit){
+            let times = parseInt(data.unit);
+            if(!isNaN(times)){
+                return scMathUtil.roundForObj(parseFloat(data.quantity)/times,getDecimal("ration.quantity"))+""
+            }
+        }
+        return data.quantity
+    },
+
+    getExistRation:function (data,referenceRationID,type) {
+        let temRation = null;
+        //先检查要更新的定额是否已经存在
+        let rations =_.filter(projectObj.project.Ration.datas,{'referenceRationID':referenceRationID,'code':data.code});
+        for(let r of rations){
+            if(type == mbzm_obj.locateMap.AFTERRATION){//如果是生成在主定额后面的位置
+                let mainRationNode = projectObj.project.mainTree.getNodeByID(referenceRationID);
+                if(r.billsItemID == mainRationNode.data.billsItemID){//如果清单ID相同, 说明是兄弟节点,位置相同
+                    temRation = r;
+                    break;
+                }
+            }
+            let billsNode = projectObj.project.mainTree.getNodeByID(r.billsItemID);
+            if(billsNode){//将父清单与要生成的清单比较,看是否一致
+                if(type == mbzm_obj.locateMap.INMEASURE && billsNode.data.type ==billType.BILL){
+                    if(!_.isEmpty(data.billID)){
+                        //说明生成位置已经有定额了,只需更新消耗量就好
+                        if(data.billID == r.billsItemID){
+                            temRation = r;
+                            break;
+                        }
+                    }else if(!_.isEmpty(data.billsLocation)){//按清单编号到找对应的位置
+                        if(billsNode.data.code && billsNode.data.code.indexOf(data.billsLocation)!=-1) {
+                            temRation = r;
+                            break;
+                        }
+                    }
+                }else if(type == mbzm_obj.locateMap.INFBFX && (billsNode.data.type ==billType.FX||billsNode.data.type ==billType.BX)){
+                    if(!_.isEmpty(data.fxID) && data.fxID == r.billsItemID){//分项、补项下有对应的定额
+                        temRation = r;
+                        break;
+                    }
+                }
+            }
+        }
+
+        return temRation;
     }
 };
 
 $('#createLocation').change(function(){
     let me = mbzm_obj;
     let pcol = _.findIndex(me.setting.header,{dataCode:"position"});
-    me.setting.header[pcol].visible =  $(this).val() == 3?false:true;
+    me.setting.header[pcol].visible =  $(this).val() == mbzm_obj.locateMap.AFTERRATION?false:true;
     me.refreshSheetData();
+});
+
+
+$('#next_mbzm').click(function () {
+    let mainSheet = projectObj.mainSpread.getActiveSheet();
+    let selection = mainSheet.getSelections()[0];
+    let node =  projectObj.project.mainTree.selected;
+    let index = node.serialNo();
+    let next = null;
+    for(let i = index+1;i< projectObj.project.mainTree.items.length;i++){
+        let temNode =  projectObj.project.mainTree.items[i];
+        if(temNode && temNode.sourceType == ModuleNames.ration){
+            let  template = projectObj.project.ration_template.getTemplateByRationID(temNode.data.ID);
+            if(template) {
+                next = temNode;
+                break;
+            }
+        }
+    }
+    if(next){
+        let row = next.serialNo();
+        let col = selection.col?selection.col:0;
+        mainSheet.setSelection(row, col, selection.rowCount, selection.colCount);
+        projectObj.mainController.setTreeSelected(next);
+        mainSheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
+    }
+});
 
+$('#apply_mbzm').click(function () {
+    mbzm_obj.applyTemplate();
 });

+ 2 - 2
web/building_saas/main/js/views/project_view.js

@@ -308,8 +308,8 @@ var projectObj = {
                             if(node.data.type == billType.BX){//从清单库中找到标准清单的话,要把补项改成分项
                                 node.data.type = billType.FX;
                             }
-                            sortItems(data.items, data.itemCharacter);
-                            sortItems(data.jobs, data.jobContent);
+                            //sortItems(data.items, data.itemCharacter);//2018-12-03 这里改成在后端获取
+                           // sortItems(data.jobs, data.jobContent);
                             pageCCOprObj.setItemContentNode(node, data.jobContent, data.itemCharacter, node.data.name);
                             pageCCOprObj.setCacheAndShow(node);
                         }

+ 32 - 17
web/building_saas/main/js/views/sub_view.js

@@ -184,8 +184,6 @@ function adaptiveTzjnrWidth() {
     //排版规则工具条宽度
     const typeSettingWidth = 30;
     let tzjnrWidth = $('#tabCon').width();
-    console.log("set jobDiv");
-    console.log(subObj.TZJNRrePercent);
     //let tzjnrWidth = $(window).width() - $('.main-nav').width() - $('.main-side').width();
     //2018-11-23 zhang 需求两个表格默认占比为25%:75%  还要可拖动
     let extWidth = $('#add-rule').is(':visible')? tzjnrWidth / 3:typeSettingWidth;
@@ -370,8 +368,8 @@ function saveAddRule(){
 }
 
 // 添加位置选择
-$("#add-position").change(function() {
-    const selected = $(this).children(":selected").val();
+function changeAddPosition(save = false) {
+    const selected = $('#add-position').children(":selected").val();
     const addContentEle = $("#add-content");
     const displayFormatEle = $("#display-format");
     const characterFormatEle = $("#character-format");
@@ -393,11 +391,16 @@ $("#add-position").change(function() {
             addContentEle.val(1);
             break;
     }
-    saveAddRule();
+    if (save) {
+        saveAddRule();
+    }
+}
+$("#add-position").change(function() {
+    changeAddPosition(true);
 });
 // 添加内容选择
-$("#add-content").change(function() {
-    const selected = $(this).children(":selected").val();
+function changeAddContent(save = false) {
+    const selected = $('#add-content').children(":selected").val();
     const characterFormatEle = $("#character-format");
     const childDisplayFormatEle = $("#child-display-format");
     const serialTypeEle = $("#serial-type");
@@ -437,7 +440,12 @@ $("#add-content").change(function() {
             childDisplayFormatEle.attr('disabled', 'disabled');
             break;
     }
-    saveAddRule();
+    if (save) {
+        saveAddRule();
+    }
+}
+$("#add-content").change(function() {
+    changeAddContent(true);
 });
 
 //显示格式
@@ -451,11 +459,12 @@ $('#character-format').change(function () {
 });
 
 // 子目生成方式选择事件
-$("#child-display-format").change(function() {
-    const selected = $(this).children(":selected").val();
+function changeChildDisplay(save = false) {
+    const selected = $('#child-display-format').children(":selected").val();
     const serialTypeEle = $("#serial-type");
-    // 如果是编号+定额名称则序号格式不能选择
-    if (selected === '1') {
+    const addContent = $('#add-content').val();
+    // 如果添加内容是定额子目且子目生成方式是编号+定额名称则序号格式不能选择
+    if (addContent === '5' && selected === '1') {
         // 默认选中数字显示模式
         serialTypeEle.val("");
         serialTypeEle.attr('disabled', 'disabled');
@@ -463,7 +472,13 @@ $("#child-display-format").change(function() {
         serialTypeEle.val(1);
         serialTypeEle.removeAttr('disabled');
     }
-    saveAddRule();
+    if (save) {
+        saveAddRule();
+    }
+
+}
+$("#child-display-format").change(function() {
+    changeChildDisplay(true);
 });
 
 //序号格式
@@ -513,17 +528,17 @@ function setRule(setting) {
         return;
     }
     $("#add-position").val(setting.position);
-    $("#add-position").change();
+    changeAddPosition(false);
 
     $("#add-content").val(setting.addContent);
-    $("#add-content").change();
+    changeAddContent(false);
 
     $("#display-format").val(setting.displayFormat);
 
     $("#character-format").val(setting.characterFormat);
 
     $("#child-display-format").val(setting.childDisplayFormat);
-    $("#child-display-format").change();
+    changeChildDisplay(false);
 
     $("#serial-type").val(setting.serialType);
 
@@ -549,8 +564,8 @@ function refreshSubSpread(){
     } else{
         if(subSpread) subSpread.refresh();
         if(MaterialController.spread) MaterialController.spread.refresh();
-        BillsElf.refreshWorkBook();
     }
+    BillsElf.refreshWorkBook();
     if($('#linkZMHS').hasClass('active')) zmhs_obj.refresh();
     if($('#linkMBZM').hasClass('active')) mbzm_obj.refresh();
 }