Bläddra i källkod

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

chenshilong 7 år sedan
förälder
incheckning
aee3d981f4

+ 17 - 0
modules/fee_rates/controllers/fee_rates_controller.js

@@ -56,6 +56,7 @@ module.exports = {
     changeFeeRateFileFromOthers:changeFeeRateFileFromOthers,
     setFeeRateToBill:setFeeRateToBill,
     updateFeeRate:updateFeeRate,
+    updateFeeRates:updateFeeRates,
     updateRates:updateRates,
     feeRateFileSaveAs:feeRateFileSaveAs
 }
@@ -214,6 +215,22 @@ async function updateFeeRate(req,res) {
     res.json(result);
 }
 
+async function updateFeeRates(req,res) {
+    let result={
+        error:0
+    }
+    try {
+        let data = req.body.data;
+        let uresult= await feeRateFacde.updateFeeRates(data);
+        result.data=uresult;
+    }catch (err){
+        console.log(err);
+        result.error=1;
+        result.message = err.message;
+    }
+    res.json(result);
+}
+
 function updateRates(req,res){
     let result={
         error:0

+ 19 - 0
modules/fee_rates/facade/fee_rates_facade.js

@@ -30,6 +30,7 @@ module.exports={
     getGCFeeRateFiles: getGCFeeRateFiles ,
     setFeeRateToBill:setFeeRateToBill,
     updateFeeRate:updateFeeRate,
+    updateFeeRates:updateFeeRates,
     updateRates:update_rates,
     feeRateFileSaveAs:feeRateFileSaveAs,
     getFeeRateByID:getFeeRateByID
@@ -363,6 +364,24 @@ async function updateFeeRate(data) {
    return  await feeRateModel.findOneAndUpdate(data.query,data.doc);
 }
 
+async function updateFeeRates(datas){//批量更新费率
+    datas = JSON.parse(datas);
+    let tasks = [];
+    for(let d of datas){
+        let task = {
+                updateOne:{
+                    filter:d.query,
+                    update:d.doc
+                }
+        }
+        tasks.push(task);
+    }
+    tasks.length > 0 ?  await feeRateModel.bulkWrite(tasks) : '';
+    return 'OK';
+}
+
+
+
 async function changeFeeRateFileFromCurrent(jdata){
     let data = JSON.parse(jdata);
     let newFeeRateFile=data.newFeeRateFile;

+ 1 - 0
modules/fee_rates/routes/fee_rates_route.js

@@ -20,6 +20,7 @@ module.exports = function (app) {
     frRouter.post('/changeFeeRateFileFromOthers', frController.changeFeeRateFileFromOthers);
     frRouter.post('/setFeeRateToBill', frController.setFeeRateToBill);
     frRouter.post('/updateFeeRate', frController.updateFeeRate);
+    frRouter.post('/updateFeeRates', frController.updateFeeRates);
     frRouter.post('/updateRates', frController.updateRates);
     frRouter.post('/feeRateFileSaveAs', frController.feeRateFileSaveAs);
     app.use('/feeRates',frRouter);

+ 17 - 11
modules/main/controllers/bills_controller.js

@@ -181,7 +181,23 @@ module.exports = {
         }
         res.json(result);
     },
+    //下载导入清单示例
+    downloadExample: async function(request, response) {
+        try {
+            const filePath = './public/static/uploadExample.xlsx';
+            const stats = fs.statSync(filePath);
+            // 下载相关header
+            response.set({
+                'Content-Type': 'application/octet-stream',
+                'Content-Disposition': 'attachment; filename=uploadExample.xlsx',
+                'Content-Length': stats.size
+            });
+            fs.createReadStream(filePath).pipe(response);
+        } catch (error) {
+            response.end(error);
+        }
 
+    },
 
     upload: async function(req, res){
         let responseData = {
@@ -327,8 +343,6 @@ function rowExistData(rowData){
 }
 //提取excel表数据中的有效数据(去表头表尾,提取其中的excel数据)(根据fixedBill获取栏头占行数)
 function getValidImportData(sheetData, fixedBill){
-    console.log(`sheetData`);
-    console.log(sheetData);
     let withingD = false;
     let validData = [];
     for(let r = 0; r < sheetData.length; r++){
@@ -349,23 +363,17 @@ function getValidImportData(sheetData, fixedBill){
                 withingD = false;
             }
         }
-        /*console.log(`rData`);
-        console.log(rData);
-        console.log(withingD);
-        console.log(rowExistData(rData));*/
         if(withingD && rowExistData(rData)){
             validData.push(rData);
         }
     }
-    /*console.log(`validData`);
-    console.log(validData);*/
     return validData;
 }
 
 function getImportFlag(sheetName){
     const fixedItem = {'分部分项': fixedFlag.SUB_ENGINERRING, '施工技术措施项目': fixedFlag.CONSTRUCTION_TECH, '施工组织措施项目': fixedFlag.CONSTRUCTION_ORGANIZATION};
     for(let flag in fixedItem){
-        if(sheetName.indexOf(flag) > 0){
+        if(sheetName.includes(flag)){
             return fixedItem[flag];
         }
     }
@@ -506,8 +514,6 @@ function parseToBillData(validData, colMapping, fixedBill, projectID, stdData){
     for(let i in billIdx){
         rst.push(billIdx[i]);
     }
-    console.log('rst');
-    console.log(rst);
     return rst;
 }
 

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

@@ -19,6 +19,7 @@ module.exports = function (app) {
     billsRouter.post('/reorganizeFBFX', billsController.reorganizeFBFX);
     billsRouter.post('/pasteBlock', billsController.pasteBlock);
     billsRouter.post('/upload', billsController.upload);
+    billsRouter.get('/downloadExamp', billsController.downloadExample);
     app.use('/bills', billsRouter);
 };
 

+ 1 - 2
modules/reports/rpt_component/jpc_flow_tab.js

@@ -52,8 +52,7 @@ JpcFlowTabSrv.prototype.createNew = function(){
         let private_inner_add_grp_rec = function(vi) {
             let hasFullGrp = true, couldBreak = false;
             for (let i = 0; i < grp_lines; i++) {
-                // if ( ((vi + insertedGrpAmt * grp_lines) + i + 1) >= (maxRecPerPage - preAmt)) {
-                if ( (vIdx.length + i ) >= maxRecPerPage) {
+                if (vIdx.length >= maxRecPerPage) {
                     for (let j = i; j < grp_lines; j++) {
                         grpPageInfo[JV.PROP_PRE_ADD_GRP_REC_INFO].push(j);
                     }

+ 34 - 0
modules/reports/util/rpt_construct_data_util.js

@@ -299,6 +299,37 @@ function summaryData(sourceData, handleCfg, prjData){
             tempRstArr.push(item);
         }
     }
+    let private_cal_before_sum = function () {
+        for (let calcAheadObj of handleCfg[JV.PROP_SUM_CALC_AHEAD]) {
+            if (!curParentPrjData[calcAheadObj["seeking_parent"]]) curParentPrjData[calcAheadObj["seeking_parent"]] = getModuleDataByKey(prjData, calcAheadObj["seeking_parent"]);
+            for (let pDataItem of curParentPrjData[calcAheadObj["seeking_parent"]].data) {
+                let data = (pDataItem._doc)?pDataItem._doc:pDataItem;
+                for (let item of tempRstArr) {
+                    if (item[calcAheadObj["seeking_key"]] === data[calcAheadObj["parent_key"]]) {
+                        for (let sumKey of handleCfg[JV.PROP_SUM_SUM_KEYS]) {
+                            switch (calcAheadObj[JV.PROP_SUM_CACL_TYPE]) {
+                                case "+":
+                                    item[sumKey] = parseFloat(item[sumKey]) + parseFloat(data[calcAheadObj["calc_property"]]);
+                                    break;
+                                case "-":
+                                    item[sumKey] = parseFloat(item[sumKey]) - parseFloat(data[calcAheadObj["calc_property"]]);
+                                    break;
+                                case "*":
+                                    item[sumKey] = item[sumKey] * parseFloat(data[calcAheadObj["calc_property"]]).toFixed(4);
+                                    break;
+                                case "/":
+                                    item[sumKey] = item[sumKey] / parseFloat(data[calcAheadObj["calc_property"]]).toFixed(4);
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+    };
     let private_get_grp_key = function (item) {
         let keys = [];
         for (let cfg of handleCfg[JV.PROP_SUM_GROUP_KEYS]) {
@@ -318,6 +349,9 @@ function summaryData(sourceData, handleCfg, prjData){
         return ( "grp_key_" + keys.join('_'));
     };
     let sumObj = {};
+    if (handleCfg[JV.PROP_SUM_CALC_AHEAD] && handleCfg[JV.PROP_SUM_CALC_AHEAD].length > 0) {
+        private_cal_before_sum();
+    }
     for (let dtl of tempRstArr) {
         let grpKey = private_get_grp_key(dtl);
         if (sumObj[grpKey] === null || sumObj[grpKey] === undefined) {

BIN
public/static/uploadExample.xlsx


+ 8 - 0
public/web/id_tree.js

@@ -229,6 +229,14 @@ var idTree = {
             this.expanded = expanded;
             setNodesVisible(this.children, expanded);
         };
+
+        Node.prototype.setExpandedNoRecur = function (expanded) {
+            this.expanded = expanded;
+            this.visible = expanded && this.visible;
+            for(let node of this.children){
+                node.visible = expanded && node.visible;
+            }
+        };
         /*Node.prototype.vis = function () {
             return this.parent ? this.parent.vis() && this.parent.expanded() : true;
         };*/

+ 2 - 0
public/web/rpt_value_define.js

@@ -80,6 +80,8 @@ const JV = {
     PROP_SORT_KEYS: "排序键值集",
     PROP_SUM_GROUP_KEYS: "分组键值集",
     PROP_SUM_SUM_KEYS: "统计键值集",
+    PROP_SUM_CALC_AHEAD: "统计前计算",
+    PROP_SUM_CACL_TYPE: "计算类型",
     PROP_FIELD_EXP_MAP: "mapExpression",
 
     NODE_FONT_COLLECTION: "font_collection",

+ 1 - 0
web/building_saas/js/global.js

@@ -24,6 +24,7 @@ function autoFlashHeight(){
     $(".main-data-side-search").height($(window).height()-headerHeight-toolsbarHeight-64);
     $(".side-content").height($(window).height()-headerHeight );
     $(".poj-list").height($(window).height()-headerHeight-toolsbarHeight);
+    $(".gc-list").height($(window).height()-headerHeight-toolsbarHeight-40);
     $(".form-view").height($(window).height()-headerHeight-ftoolsbarHeight);
     $(".form-list").height($(window).height()-headerHeight-50 );
 

+ 2 - 1
web/building_saas/main/html/main.html

@@ -272,7 +272,7 @@
                                       </div>
                                       <div class="row" id="stdBillsRemarkTab">
                                           <div class="col-lg-12 p-0">
-                                              <textarea class="form-control" id="stdBillsRemark" rows="8" readonly="true"></textarea>
+                                              <textarea class="form-control" id="stdBillsRemark" style="width: 100%; height: 100%" readonly="true"></textarea>
                                           </div>
                                       </div>
                                   </div>
@@ -1071,6 +1071,7 @@
                     <div class="alert alert-success mt-3" id="uploadAlert" role="alert" style="display: none;">
                         广东XXXX项目清单.xlsx 准备导入上传
                     </div>
+                    <button type="button" class="btn btn-primary" id="uploadExample">示例</button>
                 </div>
                 <div class="modal-footer">
                     <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>

+ 86 - 32
web/building_saas/main/js/controllers/block_controller.js

@@ -67,19 +67,32 @@ let BlockController = {
         return null;
     },
 
-    copyBlock:function (selected) {
+    copyBlock:function (selection) {
         let startTime = +new Date();
         let blockOjb = {
-            compilationID:projectInfoObj.projectInfo.compilation
+            compilationID:projectInfoObj.projectInfo.compilation,
+            datas:[]
         };
-        if(selected.sourceType == projectObj.project.Bills.getSourceType()){
-            blockOjb.firstNodeType = selected.data.type;
-        }else if(selected.sourceType == projectObj.project.Ration.getSourceType()){
+        let firstNode = projectObj.project.mainTree.items[selection.row];
+        let copyNodes = [firstNode];
+        if(selection.rowCount > 1){
+            for(let i = 1;i<selection.rowCount;i ++){
+                let temNode = projectObj.project.mainTree.items[selection.row + i];
+                if(this.copyBtnDisable(temNode) == false&&temNode.getParentID() != -1 && temNode.getParentID() == firstNode.getParentID() ){//多选时,与选中的第一个节点同一层次的才复制,即父节点一样的,其它的忽略,copyBtnDisable 判断要为false
+                    copyNodes.push(temNode);
+                }
+            }
+        }
+        if(firstNode.sourceType == projectObj.project.Bills.getSourceType()){
+            blockOjb.firstNodeType = firstNode.data.type;
+        }else if(firstNode.sourceType == projectObj.project.Ration.getSourceType()){
             blockOjb.firstNodeType = blockType.RATION;
         }
-        blockOjb.isFBFX = projectObj.project.Bills.isFBFX(selected);
+        blockOjb.isFBFX = projectObj.project.Bills.isFBFX(firstNode);
         let ration_glj_Map = _.groupBy(projectObj.project.ration_glj.datas, 'rationID');
-        blockOjb.data = this.getNodeDatas(selected,ration_glj_Map);
+        for(let cNode of copyNodes){
+            blockOjb.datas.push(this.getNodeDatas(cNode,ration_glj_Map));
+        }
         let getDataTime = +new Date();
         console.log(`复制所用时间——${getDataTime - startTime}`);
         blockOjb.copyTime = +new Date();//设置复制时间,可以用来做过期处理
@@ -142,8 +155,12 @@ let BlockController = {
         if(Bills.isFBFX(selected)){//  (2.1)、焦点行属于“分部分项工程”:
             //复制块的第一层、焦点行的类型都是“分部”
             if(blockData.firstNodeType == blockType.FB && isFB(selected)){
-                //默认为当前行的后项,可选前项、子项。
-                setRadioProp('sub_node',{checked:false,disabled:false});
+                if(selected.children.length > 0 && isFXorBX(selected.children[0])){//焦点行分部下有分项补项,弹出“粘贴位置选择”,默认为当前行的后项,可选前项,子项灰显。
+                    setRadioProp('sub_node',{checked:false,disabled:true});
+                }else {
+                    //默认为当前行的后项,可选前项、子项。
+                    setRadioProp('sub_node',{checked:false,disabled:false});
+                }
             }
             //复制块的第一层、焦点行的类型都是“分项”或补项
             if(blockIsFXorBX(blockData.firstNodeType) && isFXorBX(selected)){
@@ -202,6 +219,7 @@ let BlockController = {
         let project = projectObj.project;
         let Bills = project.Bills;
         let parent = null,next = null,pre = null;
+        let firstParentID = null, lastNextID = null;
         let updateData = [],billUpdate = null;
         let billsIDMap = {};//用来做新旧ID映射
         if(blockData.compilationID != projectInfoObj.projectInfo.compilation){//如果编办不一样,不能复制
@@ -225,23 +243,27 @@ let BlockController = {
         let parentID = parent?parent.getID():-1;
         let nextID = next?next.getID():-1;
         if(blockData.firstNodeType == blockType.RATION){ //复制的是定额,需根据新的父项信息和工程量明细计算工程量
-            blockData.data.billsItemID = parentID;
-            let billsQuantity = scMathUtil.roundForObj(parent.data.quantity,getDecimal("quantity",parent));
-            this.calcRationQuantityAndContain(billsQuantity,blockData.data);
-            //如果粘贴位置不属于分部分项工程,或者不是安装工程,则把安装增加费内容置空
-            if(!Bills.isFBFX(parent)|| projectInfoObj.projectInfo.property.engineering!=engineeringType.BUILD_IN){
-                blockData.data.ration_installations = [];
+            for(let d of blockData.datas){
+                d.billsItemID = parentID;
+                let billsQuantity = scMathUtil.roundForObj(parent.data.quantity,getDecimal("quantity",parent));
+                this.calcRationQuantityAndContain(billsQuantity,d);
+                //如果粘贴位置不属于分部分项工程,或者不是安装工程,则把安装增加费内容置空
+                if(!Bills.isFBFX(parent)|| projectInfoObj.projectInfo.property.engineering!=engineeringType.BUILD_IN){
+                    d.ration_installations = [];
+                }
             }
             //计算序列号
             this.calcRationSerialNo(parentID,blockData,updateData,pre,next);
         }else {
-            blockData.data.ParentID = parentID;
-            blockData.data.NextSiblingID=nextID;
+             firstParentID = parentID;
+             lastNextID = nextID;
+          /*  blockData.data.ParentID = parentID;
+            blockData.data.NextSiblingID = nextID;*/
             if(pre){
-                billUpdate = {type:blockData.data.sourceType,query:{ID:pre.getID()},doc:{NextSiblingID:blockData.data.ID}};
+                billUpdate = {type:blockData.datas[0].sourceType,query:{ID:pre.getID()},doc:{NextSiblingID:blockData.datas[0].ID}};
             }
         }
-        let dataMap = this.preparePasteData(blockData.data,billsIDMap);
+        let dataMap = this.preparePasteData(blockData.datas,billsIDMap,firstParentID,lastNextID);
         if(billUpdate){
             billUpdate.doc.NextSiblingID = billsIDMap[billUpdate.doc.NextSiblingID];
             updateData.push(billUpdate);
@@ -273,7 +295,7 @@ let BlockController = {
         project.quantity_detail.addDatasToList(result.quantity_details);
         project.ration_glj.addDatasToList(result.ration_gljs);
         project.ration_coe.addDatasToList(result.ration_coes);
-        project.ration_installation.addDatasToList(result.ration_installations)
+        project.ration_installation.addDatasToList(result.ration_installations);
         for(let u of  result.updateData){
             let unode = mainTree.findNode(u.query.ID);
             if(unode){
@@ -296,10 +318,15 @@ let BlockController = {
         createParentMap(parentMap_b,bills,'bills');
         createParentMap(parentMap_r,rations,'ration');
         if(parentMap_b[parentID]){
-            firstNode = loadTreeNode(parentID,nextID,parentMap_b[parentID][0],'bills');
-
+            for(let i = 0;i < parentMap_b[parentID].length;i++){
+                let temNode = loadTreeNode(parentID,nextID,parentMap_b[parentID][i],'bills');
+                i==0?firstNode = temNode:'';
+            }
         }else if(parentMap_r[parentID]){
-            firstNode = loadTreeNode(parentID,nextID,parentMap_r[parentID][0],'ration');
+            for(let i = 0;i<parentMap_r[parentID].length;i++){
+                let temNode =  loadTreeNode(parentID,nextID,parentMap_r[parentID][i],'ration');
+                i==0?firstNode = temNode:'';
+            }
         }
 
         ProjectController.syncDisplayNewNodes(projectObj.mainController, newNodes);
@@ -358,16 +385,39 @@ let BlockController = {
 
     },
 
-    preparePasteData : function (data,billsIDMap) {
+    preparePasteData : function (datas,billsIDMap,firstParentID,lastNextID) {
         let me = this;
         me.datas = _.cloneDeep(projectObj.project.Bills.datas);
         let bills = [],rations=[],ration_gljs = [],ration_coes = [],quantity_details = [],ration_installations = [];
+        let firstBillIDs = [],lastBillID = null;//记录第一层清单的ID,和第一层的最后一个清单ID
+        let firstIDMap = {};
+        for(let i = 0 ;i< datas.length ;i++){
+            if(datas[i].sourceType == 'bills'){
+                firstBillIDs.push(datas[i].ID);
+                if(i == datas.length -1){//最后一个清单节点
+                    lastBillID =  datas[i].ID
+                }
+            }
+            eachData(datas[i]);
+        }
+        for(let f of firstBillIDs){
+            firstIDMap[billsIDMap[f]]  = f //反向映射
+        }
 
-        eachData(data);
         for(let b of bills){//更新ID
-            billsIDMap[b.ParentID]?b.ParentID = billsIDMap[b.ParentID]:'';
-            billsIDMap[b.NextSiblingID]?b.NextSiblingID = billsIDMap[b.NextSiblingID]:'';
+            if(firstIDMap[b.ID]) {//如果是第一层清单节点对应的数据,更新父ID 为当前树中的父ID
+                b.ParentID = firstParentID;
+            }else {
+                billsIDMap[b.ParentID]?b.ParentID = billsIDMap[b.ParentID]:'';
+            }
+            if(b.ID == billsIDMap[lastBillID]){//如果是第一层清单最后节点对应的数据,更新下一节点ID为插入位置的下一个节点ID
+                b.NextSiblingID = lastNextID;
+            }else {
+                billsIDMap[b.NextSiblingID]?b.NextSiblingID = billsIDMap[b.NextSiblingID]:'';
+            }
         }
+
+
         return {bills:bills,rations:rations,ration_gljs:ration_gljs,ration_coes:ration_coes,quantity_details:quantity_details,ration_installations:ration_installations};
 
         function eachData(data) {
@@ -482,20 +532,24 @@ let BlockController = {
 
     calcRationSerialNo:function (billsItemID,blockData,updateData,pre,next) {
         let br = projectObj.project.Ration.getBillsSortRation(billsItemID);
+        let firstSerialNo = 0;
         if(next == null){ //没有下一树节点,即为最后节点
-            blockData.data.serialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
+            firstSerialNo = br.length > 0 ? br[br.length - 1].serialNo + 1 : 1;
         }else {//有下一节点
             let startIndex =0;
             if(pre){
                 startIndex = br.indexOf(pre.data)+1;
             }
-            blockData.data.serialNo = br[startIndex].serialNo;
+            firstSerialNo = br[startIndex].serialNo;
             for(let i = startIndex;i < br.length; i++){
-                let br_serialNo =  i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
-                updateData.push({type:blockData.data.sourceType,query:{ID:br[i].ID},doc:{serialNo:br_serialNo}});//更新兄弟节点序列号
+                let br_serialNo =  br[i].serialNo + blockData.datas.length;    //i < br.length - 1 ? br [i + 1].serialNo : br[i].serialNo + 1;
+                 updateData.push({type:blockData.datas[0].sourceType,query:{ID:br[i].ID},doc:{serialNo:br_serialNo}});//更新兄弟节点序列号
             }
         }
-
+        for(let i = 0 ; i < blockData.datas.length;i++){
+            blockData.datas[i].serialNo = firstSerialNo;
+            firstSerialNo += 1;
+        }
     },
     calcRationQuantityAndContain : function (billsQuantity,ration) {//计算定额工程量和含量
         let EXPString = ration.quantityEXP+"";

+ 56 - 5
web/building_saas/main/js/models/fee_rate.js

@@ -184,9 +184,26 @@ var FeeRate = {
             }
         };
         FeeRate.prototype.onFeeRateChange=function (rateID,value) {
-            var node = project.mainTree.selected;
-            this.refreshCalProgramByRateID(rateID,value);
-            this.refreshBillsByRateID(rateID,value);
+           /* var node = project.mainTree.selected;
+             this.refreshCalProgramByRateID(rateID,value);
+             this.refreshBillsByRateID(rateID,value);
+             if(node){
+             if (node.sourceType==='ration' && calcProgramObj.sheet) {
+             calcProgramObj.showData(node);
+             }
+             }
+             project.calcProgram.calcAllNodesAndSave(calcAllType.catAll);
+             project.markUpdateProject({projectID:project.ID(),feeRateID:this.getActivateFeeRateFileID()},"feeRate");
+             socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());*/
+           this.onFeeRatesChange([{rateID:rateID,value:value}]);
+        };
+
+        FeeRate.prototype.onFeeRatesChange = function (infos) {//{rateID:'AAAA',value:23}
+            let node = project.mainTree.selected;
+            for(let i of infos){
+                this.refreshCalProgramByRateID(i.rateID,i.value);
+                this.refreshBillsByRateID(i.rateID,i.value);
+            }
             if(node){
                 if (node.sourceType==='ration' && calcProgramObj.sheet) {
                     calcProgramObj.showData(node);
@@ -196,6 +213,8 @@ var FeeRate = {
             project.markUpdateProject({projectID:project.ID(),feeRateID:this.getActivateFeeRateFileID()},"feeRate");
             socket.emit('feeRateChangeNotify', this.getActivateFeeRateFileID());
         };
+
+
         FeeRate.prototype.onFeeRateFileChange=function () {//整个费率文件换了,原费率文件内容不变
             this.refreshCalProgramWhenFeeFileChange();
             this.refreshBillsWhenFeeFileChange();
@@ -415,7 +434,7 @@ var FeeRate = {
 
         FeeRate.prototype.updateFeeRateByID = function (rateID,doc,callback) {
           let me = this,preKey = 'rates.$.';
-          let data = {
+          /*let data = {
               query:{
                   'ID':me.getActivateFeeRateID(),
                   'rates.ID':rateID
@@ -434,9 +453,41 @@ var FeeRate = {
             if(callback){
                 callback();
             }
-          });
+          });*/
+          me.updateFeeRatesByIDs([{rateID:rateID,doc:doc}],callback);
+
         };
 
+        FeeRate.prototype.updateFeeRatesByIDs = function(datas,callback){
+            let me = this,preKey = 'rates.$.';
+            let updateDatas = [];
+            for(let d of datas){
+                let u = {
+                    query:{
+                        'ID':me.getActivateFeeRateID(),
+                        'rates.ID':d.rateID
+                    },
+                    doc:{}
+                }
+                for(let prop in d.doc){//做了个转换,加上前缀
+                    u.doc[preKey+prop] = d.doc[prop];
+                }
+                updateDatas.push(u);
+            }
+            CommonAjax.post('/feeRates/updateFeeRates', updateDatas, function (result) {
+                //更新缓存
+                for(let d of datas){
+                    let rate = me.getFeeRateByID(d.rateID);
+                    for(let dkey in d.doc){
+                        rate[dkey] = d.doc[dkey];
+                    }
+                }
+                if(callback){
+                    callback();
+                }
+            });
+
+        };
         FeeRate.prototype.getfbUpdateData=function (rate,bill,value,editText) {
             var data=null;
             if(bill.feeRateID&&editText!=null){

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

@@ -388,11 +388,10 @@ var feeRateObject={
         sheetCommonObj.lockCells(this.mainFeeRateSheet , this.mainFeeRateSetting);
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onMainFeeRateSheetValueChange);
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.SelectionChanged, this.onMainFeeRateSelectChanged);
+        this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMainFeeRateRangeChanged);
         this.mainFeeRateSheet.bind(GC.Spread.Sheets.Events.EditStarting, function (e,args) {
-            let me =feeRateObject, row = args.row;
-            let recode = me.mainFeeRateData[row];
-            let dataCode = me.mainFeeRateSetting.header[args.col].dataCode;
-            if(dataCode=="rate"&&me.getChildrenCount(recode.ID,me.mainFeeRateData)>0){//有子节点时不能编辑费率列
+            let me =feeRateObject;
+            if(!me.mainFeeRateEditChecking(args.row,args.col)){
                 args.cancel = true;
             }
         });
@@ -416,8 +415,18 @@ var feeRateObject={
             subRateObject.initSubRateSpread(this.mainFeeRateData[0]);
         }
     },
+    mainFeeRateEditChecking:function (row,col) {//false 不能编辑,true 可以编辑
+        let me =feeRateObject;
+        let recode = me.mainFeeRateData[row];
+        let dataCode = me.mainFeeRateSetting.header[col].dataCode;
+        if(dataCode=="rate"&&me.getChildrenCount(recode.ID,me.mainFeeRateData)>0){//有子节点时不能编辑费率列
+            return false;
+        }
+        return true;
+    },
+
     onMainFeeRateSheetValueChange:function (e,info) {
-        let me = feeRateObject,updateData = {},feeRate = projectObj.project.FeeRate;
+  /*      let me = feeRateObject,updateData = {},feeRate = projectObj.project.FeeRate;
         let recode = me.mainFeeRateData[info.row];
         let fieldID = me.mainFeeRateSetting.header[info.col].dataCode;
         let value = info.newValue;
@@ -442,9 +451,69 @@ var feeRateObject={
                 feeRate.onFeeRateChange(recode.ID,value);
             }
             $.bootstrapLoading.end();
-        })
+        })*/
+        feeRateObject.updateFeerateWhenCellsChange([info]);
+    },
+    onMainFeeRateRangeChanged:function (e,info) {
+        let me = feeRateObject;
+        let changeCells = [];
+        for(let c of info.changedCells){
+            let tem = {
+                row:c.row,
+                col:c.col,
+                newValue:info.sheet.getCell(c.row,c.col).value()
+            };
+            changeCells.push(tem);
+        }
+        me.updateFeerateWhenCellsChange(changeCells);
     },
 
+    updateFeerateWhenCellsChange:function (cells) {// col,row,newValue
+        let me = feeRateObject,updateDatas = [],feeRate = projectObj.project.FeeRate;//[{rateID:rateID,doc:doc}]
+        let refreshA = [];//记录刷新条数的数组
+        for(let c of cells){
+            let temData = {};
+            let recode  = me.mainFeeRateData[c.row];
+            let fieldID = me.mainFeeRateSetting.header[c.col].dataCode;
+            let value = c.newValue;
+            let oldValue = recode[fieldID];
+            if(!me.mainFeeRateEditChecking(c.row, c.col)){
+                me.mainFeeRateSheet.setValue(c.row, c.col, oldValue);
+                continue;
+            }else if(fieldID == 'rate'&&value != null){
+                let checkResult = scMathUtil.isNumOrFormula(value);
+                if(checkResult!=null && !isNaN(checkResult)){
+                    value = scMathUtil.roundForObj(checkResult,getDecimal("feeRate"));
+                }else {
+                    setTimeout(function () {
+                        alert('当前输入的数据类型不正确,请重新输入。');
+                    },100);
+                    me.mainFeeRateSheet.setValue(c.row, c.col, oldValue);
+                    continue;
+                }
+            }
+            if(recode[fieldID] == value){//没有改变
+                continue;
+            }
+            temData[fieldID] = value ;
+            updateDatas.push({rateID:recode.ID,doc:temData});
+            refreshA.push({col:c.col,row:c.row,fieldID:fieldID,value:value,rateID:recode.ID});
+        }
+        if(updateDatas.length > 0){
+            $.bootstrapLoading.start();
+            feeRate.updateFeeRatesByIDs(updateDatas,function () {
+                let feerateInfo = [];
+                for(let r of refreshA){
+                    me.mainFeeRateSheet.setValue(r.row, r.col, r.value);
+                    if(r.fieldID == 'rate'){
+                        feerateInfo.push({rateID:r.rateID,value:r.value});
+                    }
+                }
+                feerateInfo.length > 0 ?feeRate.onFeeRatesChange(feerateInfo):'';
+                $.bootstrapLoading.end();
+            })
+        }
+    },
     onMainFeeRateSelectChanged:function (e, info) {
         let me = feeRateObject;
         let row = info.newSelections[0].row;

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

@@ -948,13 +948,16 @@ var projectObj = {
                     name: '复制整块',
                     icon: 'fa-copy',
                     disabled: function () {
-                        return BlockController.copyBtnDisable(project.mainTree.selected);
+                        let selection = projectObj.mainSpread.getActiveSheet().getSelections()[0];
+                        let firstNode = projectObj.project.mainTree.items[selection.row];//当多选的情况,用mainTree.selected判断不正确,要用第一个选中的节点
+                        return BlockController.copyBtnDisable(firstNode);
                     },
                     callback: function () {
                         $.bootstrapLoading.start();
-                        let selected = project.mainTree.selected;
+                        //let selected = project.mainTree.selected;
+                        let selections = projectObj.mainSpread.getActiveSheet().getSelections();
                         setTimeout(function () {
-                            BlockController.copyBlock(selected);
+                            BlockController.copyBlock(selections[0]);
                             $.bootstrapLoading.end();
                         },100)
 
@@ -1944,7 +1947,10 @@ function doAfterImport(resData){
         });
     }
 }
-
+//下载导入清单示例文件
+$('#uploadExample').click(function () {
+    window.location.href = '/bills/downloadExamp'
+});
 
 $(function () {
     //清空导入清单选择文件

+ 34 - 5
web/building_saas/main/js/views/std_bills_lib.js

@@ -44,7 +44,8 @@ var billsLibObj = {
         if (spread) {
             let sheet = spread.getActiveSheet();
             sheet.suspendPaint();
-            sheet.getRange(0, -1, sheet.getRowCount(), -1, GC.Spread.Sheets.SheetArea.viewport).backColor(undefined);
+            let orgColor = optionsOprObj.getOption('COLOROPTS', 'DEFAULT').backColor;
+            sheet.getRange(0, -1, sheet.getRowCount(), -1, GC.Spread.Sheets.SheetArea.viewport).backColor(orgColor);
             sheet.resumePaint();
         }
     },
@@ -186,7 +187,7 @@ var billsLibObj = {
             stdBillsTreeController.showTreeData();
             billsLibObj.setTagForHint(datas);
             showBillsRela(that.stdBillsTree.firstNode());
-
+            console.log(that.stdBillsTree.items);
             stdBillsTreeController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, showBillsRela);
             that.stdBillsSpread.unbind(GC.Spread.Sheets.Events.CellDoubleClick);
             that.stdBillsSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, function (sender, args) {
@@ -237,9 +238,12 @@ var billsLibObj = {
         });
 
         $('#stdBillsSearch>span>button').click(function () {
+            billsLibObj.clearHighLight(billsLibObj.stdBillsSpread);
             var keyword = $('#stdBillsSearch>input').val();
-
-            if (!keyword || keyword === '') {return}
+            if (!keyword || keyword === '') {
+                $('#stdBillsSearchResult').hide();
+                return;
+            }
 
             var result = that.stdBillsTree.items.filter(function (item) {
                 var codeIs = item.data.code ? item.data.code.indexOf(keyword) !== -1 : false;
@@ -250,6 +254,11 @@ var billsLibObj = {
                 return x.serialNo() - y.serialNo();
             });
             if (result.length !== 0) {
+                //展开搜索出来的节点
+                billsLibObj.expandSearchNodes(result);
+                //设置记住展开
+                sessionStorage.setItem('stdBillsLibExpState', that.stdBillsTree.getExpState(that.stdBillsTree.items));
+
                 var sel = billsLibObj.stdBillsSpread.getActiveSheet().getSelections();
                 stdBillsTreeController.setTreeSelected(result[0]);
                 billsLibObj.stdBillsSpread.getActiveSheet().setSelection(result[0].serialNo(), sel[0].col, 1, 1);
@@ -259,7 +268,8 @@ var billsLibObj = {
                 }
 
                 $('#nextStdBills').show();
-                $('#nextStdBills').click(function () {
+                $('#nextStdBills').unbind('click');
+                $('#nextStdBills').bind('click', function () {
                     var cur = that.stdBillsTree.selected, resultIndex = result.indexOf(cur), sel = billsLibObj.stdBillsSpread.getActiveSheet().getSelections();
                     if (resultIndex === result.length - 1) {
                         stdBillsTreeController.setTreeSelected(result[0]);
@@ -277,6 +287,23 @@ var billsLibObj = {
             $('#stdBillsSearchResult').show();
         });
     },
+    expandSearchNodes: function(nodes){
+        let that = this;
+        TREE_SHEET_HELPER.massOperationSheet(billsLibObj.stdBillsSpread.getActiveSheet(), function () {
+            function expParentNode(node){
+                if(node.parent && !node.parent.expanded){
+                    node.parent.setExpanded(true);
+                    expParentNode(node.parent);
+                }
+            }
+            for(let node of nodes){
+
+                expParentNode(node);
+            }
+            TREE_SHEET_HELPER.refreshTreeNodeData(that.stdBillsTreeSetting, that.stdBillsSpread.getActiveSheet(), that.stdBillsTree.roots, true);
+            TREE_SHEET_HELPER.refreshNodesVisible(that.stdBillsTree.roots, that.stdBillsSpread.getActiveSheet(), true);
+        });
+    },
     stdBillsTreeSetting: {
         "treeCol": 0,
         "emptyRows":0,
@@ -454,4 +481,6 @@ $('#closeSearchStdBills').click(function () {
     $('#stdBillsSearchResult').hide();
     $(".main-data-side-q").height($(window).height() - $(".header").height() - $(".toolsbar").height() -  $(".tools-bar-height-q").height() - 202);
     billsLibObj.clearHighLight(billsLibObj.stdBillsSpread);
+    billsLibObj.refreshBillsSpread();
+    billsLibObj.refreshBillsRelaSpread();
 });

+ 2 - 1
web/building_saas/main/js/views/std_ration_lib.js

@@ -366,9 +366,10 @@ $('#rationSearch').click(function () {
         resultObj.append(getResultHtml(result));
         $('a', resultObj).click(function () {
             resultObj.hide();
+            $(".main-data-side-search", resultObj).height(0);
+            autoFlashHeight();
             //$(".main-data-side-d").height($(window).height() - $(".header").height() - $(".toolsbar").height() -  $(".tools-bar-height-d").height() - 202);
             rationLibObj.refreshSpread();
-            $(".main-data-side-search", resultObj).height(0);
         });
         resultObj.show();
         $(".main-data-side-search", resultObj).height($(window).height() - $(".header").height() - $(".toolsbar").height() - 64);

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

@@ -6,7 +6,7 @@
         <p style="text-align: center; margin-top: 30px;">正在加载数据...</p>
     </div>-->
 </div>
-<div class="poj-list" id="gcSpread">
+<div class="gc-list" id="gcSpread">
 
 </div>
 <!--弹出恢复项目-->

+ 2 - 0
web/building_saas/pm/js/pm_gc.js

@@ -584,6 +584,8 @@ function gc_init(){
         //初始选择
         let initSel = gcTreeObj.workBook.getSheet(0).getSelections()[0] ? gcTreeObj.workBook.getSheet(0).getSelections()[0] : {row: 0, rowCount: 1};
         gcTreeObj.initSelection(initSel);
+        autoFlashHeight();
+        gcTreeObj.workBook.refresh();
         $.bootstrapLoading.end();
     });
 }

+ 2 - 0
web/building_saas/pm/js/pm_newMain.js

@@ -1257,6 +1257,8 @@ function init() {
             let initSel = projTreeObj.workBook.getSheet(0).getSelections()[0] ? projTreeObj.workBook.getSheet(0).getSelections()[0] : {row: 0, rowCount: 1};
             projTreeObj.initSelection(initSel,null,projTreeObj.workBook.getActiveSheet());
             $.bootstrapLoading.end();
+            autoFlashHeight();
+            projTreeObj.workBook.refresh();
         });
     });
     engineering = engineeringList !== null && engineeringList !== undefined ? JSON.parse(engineeringList) : [];