Selaa lähdekoodia

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

chenshilong 7 vuotta sitten
vanhempi
commit
25c972072f

+ 2 - 2
modules/pm/models/project_property_template.js

@@ -4,8 +4,8 @@
 
 //默认的小数位数,用于定义用户可编辑的字段(入库),用户不可编辑的字段在前端defaultDecima._def中定义即可
 const defaultDecimal = {
-    bills: {unitPrice: 2, totalPrice: 2},
-    ration: {quantity: 4, unitPrice: 2, totalPrice: 2},
+    bills: {unitPrice: 2, totalPrice: 0},
+    ration: {quantity: 4, unitPrice: 2, totalPrice: 0},
     glj: {quantity: 4, unitPriceHasMix: 2, unitPrice: 3},
     feeRate: 3,
     quantity_detail: 4,

+ 2 - 1
public/web/sheet/sheet_common.js

@@ -749,7 +749,8 @@ var sheetCommonObj = {
             };
         }
         TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
-            if (!_.isEmpty(this.rectInfo)&&hitinfo.x < this.rectInfo.x+this.rectInfo.rectW && hitinfo.x > this.rectInfo.x) {
+            ////方框外1像素内都有效
+            if (!_.isEmpty(this.rectInfo)&&Math.floor(hitinfo.x) <= this.rectInfo.x+this.rectInfo.rectW+2 && Math.floor(hitinfo.x) >= this.rectInfo.x-2) {
                 this.collapsed = !this.collapsed;
                 datas[row].collapsed = this.collapsed;
                 this.refreshChildrenVisible(hitinfo.sheet);

+ 3 - 1
public/web/tree_sheet/tree_sheet_helper.js

@@ -469,7 +469,9 @@ var TREE_SHEET_HELPER = {
             if (!node || node.children.length === 0) { return; }
             let centerX = hitinfo.cellRect.x + offset + node.depth() * indent + node.depth() * levelIndent + indent / 2;
             let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;
-            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
+            //方框外1像素内都有效
+            if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 &&
+                hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) {
                 node.setExpanded(!node.expanded);
                 let sheetName = hitinfo.sheet.name();
                 if(sheetName === 'stdBillsLib_bills'){

+ 1 - 1
socketdockerfile

@@ -6,6 +6,6 @@ COPY . /home/ConstructionCost
 
 RUN cnpm install 
 
-EXPOSE 3300
+EXPOSE 5500
 
 ENTRYPOINT babel-node socket.js

+ 2 - 2
web/building_saas/fee_rates/fee_rate.html

@@ -16,9 +16,9 @@
                 <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#set-lv" id="setNewFeeRate"><i class="fa fa-cog"></i> 重选标准</a>
             </div>
         </div>
-        <div class="col-lg-4 p-0">
+        <!--<div class="col-lg-4 p-0">
             <div class="form-inline py-1" style="margin-top: 5px"><input type="checkbox" id="cascadeSet" checked >  <label class="mx-2" >统一设置相同参数</label></div>
-        </div>
+        </div>-->
     </div>
 </div>
 <div class="container-fluid">

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

@@ -84,11 +84,11 @@
                     <!--<a href="javascript:void(0)" class="btn btn-sm" title="复制" ><i class="fa fa-files-o" aria-hidden="true"></i></a>
                     <a href="javascript:void(0)" class="btn btn-sm" title="剪切"><i class="fa fa-scissors" aria-hidden="true"></i></a>
                     <a href="javascript:void(0)" class="btn btn-sm" title="粘贴"><i class="fa fa-clipboard" aria-hidden="true"></i></a>-->
-                      <span class="btn btn-light btn-sm" data-toggle="tooltip" data-original-title="项目属性" data-placement="bottom">
-                        <a href="javascript:void(0);" id="openProjSet"><i class="fa fa-cog"></i></a>
+                      <span id="openProjSet" class="btn btn-light btn-sm" data-toggle="tooltip" data-original-title="项目属性" data-placement="bottom">
+                        <a href="javascript:void(0);"><i class="fa fa-cog"></i></a>
                     </span>
                     <span class="btn btn-light btn-sm" id="importSpan" data-toggle="tooltip" data-original-title="导入" data-placement="bottom">
-                        <a class="dropdown-toggle" href="#" data-toggle="dropdown"><i class="fa fa-cloud-upload"></i></a>
+                        <a id="importDropDown" class="dropdown-toggle" href="#"><i class="fa fa-cloud-upload"></i></a>
                         <div class="dropdown-menu">
                             <a id="uploadLj" class="dropdown-item" href="#import" data-toggle="modal" data-target="#import">导入报表Excel清单</a>
                             <a id="uploadGld" class="dropdown-item" href="#import" data-toggle="modal" data-target="#import">导入广联达算量Excel清单</a>
@@ -874,7 +874,7 @@
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
                                                         <div class="input-group-prepend">
-                                                            <span class="input-group-text">合价</span>
+                                                            <span class="input-group-text">金额</span>
                                                         </div>
                                                         <input type="number" name="bills-totalPrice" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
@@ -901,7 +901,7 @@
                                                 <div class="col-sm-3">
                                                     <div class="input-group input-group-sm mb-2">
                                                         <div class="input-group-prepend">
-                                                            <span class="input-group-text">合价</span>
+                                                            <span class="input-group-text">金额</span>
                                                         </div>
                                                         <input type="number" name="ration-totalPrice" class="form-control" value="2" step="1" max="6" min="0">
                                                     </div>
@@ -977,12 +977,12 @@
                                                     定额子目自动调整行高
                                                 </label>
                                             </div>
-                                            <div class="form-check">
+                                            <!--<div class="form-check">
                                                 <label class="form-check-label">
                                                     <input class="form-check-input" id="disPlayMainMaterial" type="checkbox">
                                                     定额下显示主材、设备
                                                 </label>
-                                            </div>
+                                            </div>-->
                                         </fieldset>
                                         <div id="col_setting_spread" style="height:280px;overflow:hidden">
                                         </div>

+ 3 - 1
web/building_saas/main/js/models/main_consts.js

@@ -254,7 +254,9 @@ const fixedFlag = {
     //施工机械
     CONSTRUCTION_MACHINE:25,
     //暂列金额
-    PROVISIONAL:26
+    PROVISIONAL:26,
+    //安全生产费
+    SAFE_COST:27
 };
 
 const gljKeyArray =['code','name','specs','unit','type'];

+ 3 - 2
web/building_saas/main/js/views/block_lib.js

@@ -298,8 +298,9 @@ var blockLibObj = {
             function withingClickArea(){
                 return hitinfo.x > centerX + halfBoxLength && hitinfo.x < centerX + halfBoxLength + imgWidth + indent/2+3 + textLength;
             }
-
-            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
+            //方框外1像素内都有效
+            if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 &&
+                hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) {
                 node.setExpanded(!node.expanded);
                 TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
                     let iCount = node.posterityCount(), i, child;

+ 92 - 18
web/building_saas/main/js/views/fee_rate_view.js

@@ -543,28 +543,102 @@ var feeRateObject={
             subRateObject.initSubRateSpread(me.mainFeeRateData[row]);
         }
     },
-    updateBySelect:function (rate,selectMap,mapID) {
-        let selected = this.mainFeeRateSheet.getSelections()[0];
-        projectObj.project.FeeRate.backupDatas();
-        let item = this.mainFeeRateData[selected.row];
-        item.rate = rate;
-        for(let key in selectMap){
-            let recode =  item.subFeeRate.recodes[key];
-            let optionList = recode.optionList;
-            for(let o of optionList){
-                if(o.value==selectMap[key]){
-                    o.selected=true;
-                }else {
-                    o.selected = false;
+    setRateFromSub:function (subRate,value,subList) {
+         let me = feeRateObject,feeRate =  projectObj.project.FeeRate;
+         let rates = feeRate.getActivateFeeRate().rates;
+         let updateDatas = [];
+         //对于有子节点的记录和可输入的记录,只支持一个参数(因为还要内插法取费率值),如果要支持两个以上的参数,valueMap要再改下~~~~
+         for(let r of rates){
+             if(gljUtil.isDef(r.subFeeRate)){
+                 let valueArray=[];//用来存参数的值
+                 let temP =null;//这个用来存储需要内插法记算的时候,同时,树节点的子节点改变也计在这里, 这样,改变temP的值,会体现在保存subRecode
+                 let match = false;
+                 let temR = _.cloneDeep(r);//临时存储
+                 for(let p of temR.subFeeRate.recodes){
+                     if(p.name == subRate.name){
+                         temP = p;
+                         match = true;
+                     }
+                     let setValue = false;
+                     for(let o of p.optionList){
+                         if(match == true) {//匹配上了,改对应的selected 为 true
+                             if(o.name == value){
+                                 o.selected = true;
+                                 valueArray.push(value);
+                                 setValue = true;
+                             }else {
+                                 o.selected = false;
+                             }
+                         }else {//没有匹配上的,直接取值就可以
+                             if(o.selected == true)  valueArray.push(o.name);
+                         }
+                     }
+                     if(match==true && setValue ==false) valueArray.push(value);//如果匹配上了,但是setValue为false,说明没有满足和选项,要用内插法或超出倍数算值
+                 }
+                 if(match == true){//说明要改rate的值,先从valueMap中去查
+                     if(subList && temP.subList && temP.subList.length > 0){
+                         temP.subList = subList;// 设置树节点的子节点的值
+                     }
+                     let doc = {"subFeeRate":temR.subFeeRate};
+                     let valueKey = valueArray.join('-');
+                     let valueMaps = r.subFeeRate.valueMaps;
+                     let rate = _.find(valueMaps,{"ID":valueKey});
+                     if(isDef(rate)) {//找到了,直接改费率值
+                         doc.rate = rate.value;
+                     }else {//没找到,用内插法或步长算值
+                         let ltRate = null;//
+                         let gtRate = null;
+                         let lastRate = null;
+                         temP.value = scMathUtil.roundForObj(value,getDecimal("feeRate")) ;
+                         for(let v of valueMaps){
+                            if(parseFloat(v.value)<parseFloat(value)){
+                                ltRate = v;
+                            }else if(parseFloat(v.value)>parseFloat(value)){
+                                gtRate = v;
+                            }
+                            lastRate = v;
+                         }
+                         if(gljUtil.isDef(ltRate)&&gljUtil.isDef(gtRate)){//已经找到前后的值了
+                             let step = scMathUtil.roundForObj(gtRate.value - ltRate.value,getDecimal("process"))
+                             let total =  parseInt(gtRate.ID) - parseInt(ltRate.ID)
+                             doc.rate =getRateByStep(ltRate.value,total,parseFloat(value) - parseInt(ltRate.ID),step);
+                         }else if(gljUtil.isDef(ltRate)&&gtRate == null){//说明是超出了选项的最大值
+                             let share = parseFloat(value) - parseInt(ltRate.ID);//超出了多少
+                             doc.rate = getRateByStep(ltRate.value,temP.step,share,temP.amount)
+                         }
+                     }
+                     if(isDef(doc.rate)){
+                         updateDatas.push({rateID:r.ID,doc:doc});
+                         me.sumParentRate(r.ID,doc.rate,updateDatas);
+                     }
+                 }
+             }
+         }
+         console.log(updateDatas);
+        if(updateDatas.length > 0){
+            $.bootstrapLoading.start();
+            feeRate.updateFeeRatesByIDs(updateDatas,function () {
+                let feerateInfo = [];
+                for(let u of updateDatas){
+                    feerateInfo.push({rateID:u.rateID,value:u.doc["rate"]});
                 }
-            }
+                subRateObject.showSubRateData();
+                me.showMainFeeRateData();
+                feerateInfo.length > 0 ?feeRate.onFeeRatesChange(feerateInfo):'';
+                $.bootstrapLoading.end();
+            })
         }
-        if($('#cascadeSet').prop('checked')){
-            this.cascadeSetRates(item,selected.row,mapID,selectMap);
-        }else {
-            projectObj.project.FeeRate.batchUpdateFeeRate([{rateIndex:selected.row,rate:item}],feeRateObject.activateFeeRate);
+        function getRateByStep(ltValue,total,share,step) {
+            let p = scMathUtil.roundForObj(share/total,getDecimal("process"));
+            let a = scMathUtil.roundForObj(step * p,getDecimal("process")) ;
+            return scMathUtil.roundForObj(ltValue + a,getDecimal("feeRate"))
         }
+
+
+
     },
+
+
     cascadeSetRates:function(selectedItem,sourceRow,mapID,selectMap){
         let items=[];
         items.push({rateIndex:sourceRow,rate:selectedItem});

+ 2 - 5
web/building_saas/main/js/views/project_info.js

@@ -8,15 +8,12 @@ var projectInfoObj = {
         let fullPath = [], i, pm = '<span class="text-truncate"><a href="/pm">项目管理</a></span>', angleRight = '<span class="text-truncate"><i class="fa fa-angle-right fa-fw"></i></span>';
         if (proj) {
             let pathArr = proj.fullPath;
-            let engName = pathArr[pathArr.length -2] || '',
-                projectName = pathArr[pathArr.length -3] || '',
-                folderName = pathArr[pathArr.length -4] || '';
+            let projectName = pathArr[pathArr.length -2] || '',
+                folderName = pathArr[pathArr.length -3] || '';
             let newHtml = `   <span data-toggle="tooltip" data-placement="bottom" data-original-title="${folderName}"><i class="fa fa-folder-open-o"></i>...</span>
                 <span class="text-muted px-1">\</span>
                 <span data-toggle="tooltip" data-placement="bottom" data-original-title="${projectName}"><i class="fa fa-cubes"></i>...</span>
                 <span class="text-muted px-1">\</span>
-                <span data-toggle="tooltip" data-placement="bottom" data-original-title="${engName}"><i class="fa fa-cube"></i>...</span>
-                <span class="text-muted px-1">\</span>
                  <span><i class="fa fa-sticky-note-o"></i></span>
                 <span class="text-truncate"  data-toggle="tooltip" data-placement="bottom" data-original-title="${proj.name}">&nbsp;${proj.name}</span>
                 ${projectReadOnly ?

+ 10 - 3
web/building_saas/main/js/views/project_property_basicInfo.js

@@ -398,9 +398,16 @@ let basicInfoView = {
         }
         TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
             var recode = data[hitinfo.row];
+            let offset = -1,
+                indent = 20,
+                halfBoxLength = 5;
+            let centerX = hitinfo.cellRect.x + offset + indent / 2;
+            let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2
             if(recode&&recode.hasOwnProperty('items')){
-                var hoffset= hitinfo.cellRect.x+3;
-                if (hitinfo.x > hoffset && hitinfo.x < hoffset + 10){
+                //方框外1像素内都有效
+                const boxLengh = 10;
+                if (hitinfo.x >= centerX - halfBoxLength - 1 && hitinfo.x <= centerX + halfBoxLength + 1 &&
+                    hitinfo.y >= centerY - halfBoxLength - 1 && hitinfo.y <= centerY + halfBoxLength + 1) {
                     var collapsed = recode.collapsed==undefined?true:recode.collapsed;
                     collapsed = !collapsed
                     recode.collapsed=collapsed;
@@ -491,7 +498,7 @@ $(document).ready(function () {
     $('#openProjSet').click(function () {
         $('[data-toggle="tooltip"]').tooltip('hide');
         $('#poj-set').modal('show');
-    })
+    });
    /* $('#property_ok').bind('click', function () {
         if(basicInfoView.toUpdate(basicInfoView.orgDatas, basicInfoView.datas)){
             basicInfoView.a_updateInfo(basicInfoView.toSaveDatas(basicInfoView.datas));

+ 9 - 2
web/building_saas/main/js/views/project_property_projFeature.js

@@ -379,9 +379,16 @@ let projFeatureView = {
         }
         TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
             var recode = data[hitinfo.row];
+            let offset = -1,
+                indent = 20,
+                halfBoxLength = 5;
+            let centerX = hitinfo.cellRect.x + offset + indent / 2;
+            let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2
             if(recode&&recode.hasOwnProperty('items')){
-                var hoffset= hitinfo.cellRect.x+3;
-                if (hitinfo.x > hoffset && hitinfo.x < hoffset + 10){
+                //方框外1像素内都有效
+                const boxLengh = 10;
+                if (hitinfo.x >= centerX - halfBoxLength - 1 && hitinfo.x <= centerX + halfBoxLength + 1 &&
+                    hitinfo.y >= centerY - halfBoxLength - 1 && hitinfo.y <= centerY + halfBoxLength + 1) {
                     var collapsed = recode.collapsed==undefined?true:recode.collapsed;
                     collapsed = !collapsed
                     recode.collapsed=collapsed;

+ 18 - 1
web/building_saas/main/js/views/project_view.js

@@ -1386,7 +1386,9 @@ var projectObj = {
                         getGLJData('insert');// ProjectController.addRation(project, controller, rationType.volumePrice);
                     },
                     visible: function(key, opt){//2018-11-08  新需求,这个按钮先隐藏,有需要再放开
-                        return false;
+                        let selected = project.mainTree.selected;
+                        return selected && selected.sourceType == ModuleNames.bills &&
+                            !_.isEmpty(selected.data.flagsIndex) && selected.data.flagsIndex.fixed.flag === fixedFlag.EQUIPMENT_ACQUISITION_FEE
                     }
                 },
                 "spr2": '--------',
@@ -2261,6 +2263,21 @@ let displayLevel = function(nodes, depth, type){
         TREE_SHEET_HELPER.refreshNodesVisible(refreshNodes, projectObj.mainSpread.getActiveSheet(), true)
     });
 };
+//导入下拉
+$('#importSpan').click(function () {
+    $('[data-toggle="tooltip"]').tooltip('hide');
+    let toggle = $('#importDropDown').attr('data-toggle');
+    if (toggle) {
+        $('#importDropDown').removeAttr('data-toggle');
+    }
+    $('#importDropDown').dropdown('toggle');
+    setTimeout(function () {
+        $('#importDropDown').attr('data-toggle', 'dropdown');
+    }, 100);
+});
+$('#importDropDown').click(function () {
+    $('[data-toggle="tooltip"]').tooltip('hide');
+});
 $('body').click(function () {
     //点击完后隐藏子菜单
    if ($('#subDisplay').is(':visible')) {

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

@@ -102,10 +102,10 @@ let quantityEditObj = {
 
         QuantityEditCellType.prototype.processMouseDown = function (hitinfo) {
             let me=quantityEditObj;
-            if(isDoubleClick(this) == true && !projectReadOnly){//如果是双击,直接显示
+           /* if(isDoubleClick(this) == true && !projectReadOnly){//如果是双击,直接显示 2019-1-17 需求更改,取消双击弹出
                 me.showSelectModal(hitinfo);
                 return ;
-            }
+            }*/
            if(me.editingCell && hitinfo.row==me.editingCell.row){
                if(me.editingCell.isBtn == false){//是第一次点击,刷新显示按钮
                    me.editingCell.isBtn = true;

+ 4 - 2
web/building_saas/main/js/views/std_billsGuidance_lib.js

@@ -161,7 +161,8 @@ const billsGuidance = (function () {
                 row = newNodes[newNodes.length - 1].serialNo();
                 //有新的节点插入,也有可能定位至旧节点(批量选用的情况下)
                 if (compareData.locateNode) {
-                    row = compareData.locateNode.serialNo();
+                    //该清单节点在主树的位置
+                    row = projectObj.project.mainTree.nodes[projectObj.project.mainTree.prefix + compareData.locateNode.data.ID].serialNo();
                 }
                 sheet.setSelection(row, col, 1, 1);
                 projectObj.mainController.setTreeSelected(projectObj.mainController.tree.items[row]);//触发树节点选中事件
@@ -171,7 +172,8 @@ const billsGuidance = (function () {
                 isInserting = false;
             });
         } else if (compareData.locateNode) {
-            row = compareData.locateNode.serialNo();
+            //该清单节点在主树的位置
+            row = projectObj.project.mainTree.nodes[projectObj.project.mainTree.prefix + compareData.locateNode.data.ID].serialNo();
             sheet.setSelection(row, col, 1, 1);
             projectObj.mainController.setTreeSelected(projectObj.mainController.tree.items[row]);//触发树节点选中事件
             sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);

+ 42 - 79
web/building_saas/main/js/views/sub_fee_rate_views.js

@@ -21,36 +21,14 @@ var subRateObject={
             forOption:function (item,val) {
                 if(item.isSub == true) return item.value;//可编辑子节点
                 let o = _.find(item.optionList,{'selected':true});
-                return o?o.name:'';
+                if(gljUtil.isDef(o)){
+                    return o.name;
+                }else {
+                    if(item.editable==true) return item.value;
+                }
             }
         }
     },
-    columns: [
-        {
-            id: 'name',
-            caption: '参数名称',
-            dataField: 'name',
-            width: 250,
-            allowEditing: false
-        },
-        {
-            id: 'typeName',
-            caption: '参数值',
-            dataField: 'typeName',
-            width: 200,
-            minWidth: 50,
-            allowEditing: true,
-            presenter:'<div><select class="form-control form-control-sm" id="{{=it.ID}}" onchange="subRateObject.subRateChange(this)" style="width: 100%">  </select></div>'
-        },
-        {
-            id: 'ID',
-            caption: 'ID',
-            dataField: 'ID',
-            width: 80,
-            visible: false,
-            allowEditing: false
-        }
-    ],
     options :{
         allowSorting: false,
         showRowHeader: true,
@@ -61,27 +39,6 @@ var subRateObject={
         editUnit: 'cell',
         selectionUnit:(this.canEdit == true) ? "cell" : "row"
     },
-    createSpreadView:function () {
-        if (this.views) {
-            this.views.destroy();
-            this.views = null;
-        }
-        this.views = new GC.Spread.Views.DataView($('#subRate')[0],
-            this.datas, this.columns, new GC.Spread.Views.Plugins.GridLayout(this.options));
-
-        this.views["rowDbClick"].addHandler(function () {
-            console.log('hh')
-        });
-        this.views.invalidate();
-        document.querySelector('#subRate').focus();
-        this.addComboboxOption(this.datas);
-
-    },
-    reFreshRateViews:function(sender,args) {
-        subRateObject.datas = projectObj.project.FeeRate.getSubViewData(args.item);
-        subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(args.item);
-        subRateObject.createSpreadView();
-    },
     initSubRateSpread:function (item) {
         if(this.subRateSpread == null){
             this.subRateSpread = SheetDataHelper.createNewSpread($("#subRate")[0]);
@@ -93,7 +50,6 @@ var subRateObject={
             //this.subRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, me.onSheetValueChange);
             this.subRateSheet.name('subRateSheet');
         }
-        subRateObject.datas = projectObj.project.FeeRate.getAllSubRates();
         //subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(item);
         subRateObject.showSubRateData();
         disableRightMenu("subRate",this.subRateSpread);
@@ -105,6 +61,8 @@ var subRateObject={
         }
     },
     showSubRateData:function () {
+        let preSelections = this.subRateSheet.getSelections();
+        this.datas = projectObj.project.FeeRate.getAllSubRates();
         this.subRateSheet.setRowCount(0);
         sheetCommonObj.showData(this.subRateSheet, this.subRateSetting, this.datas);
         this.subRateSheet.setRowCount(this.datas.length);
@@ -118,6 +76,9 @@ var subRateObject={
         }
         this.subRateSheet.resumeEvent();
         this.subRateSheet.resumePaint();
+        if(preSelections){//定位光标到之前的位置
+            this.subRateSheet.setSelection(preSelections[0].row,preSelections[0].col,preSelections[0].rowCount,preSelections[0].colCount);
+        }
     },
     onSubRateSelectChanged:function (e,info) {
         info.sheet.repaint();
@@ -159,39 +120,41 @@ var subRateObject={
             $('#'+item.ID).val(selectvalue);
         })
     },
-    subRateChange:function(select){
-        let me = subRateObject;
-        let selectValueList=[];
-        let selectMap={};
-        if(me.datas&&me.datas.length>0){
-            $.bootstrapLoading.start();
-            _.forEach(me.datas,function (d,key) {
-                let selectValue = $('#'+d.ID).val();
-                selectValueList.push(selectValue);
-                selectMap[key]=selectValue;
-            })
-            let mapID =selectValueList.join('-');
-            let rate = me.valueMap[mapID];
-            feeRateObject.updateBySelect(rate,selectMap,mapID);
-        }
-    },
     onSubRateValueChange:function (e,info) {
-        console.info(info);
-        let me = subRateObject, selectValueList=[],selectMap={};
-        if(me.datas&&me.datas.length>0){
-            _.forEach(me.datas,function (d,key) {
-                if(info.row == key){
-                    selectMap[key]=info.newValue;
-                }else {
-                    let o = _.find(d.optionList,{'selected':true});
-                    selectMap[key]=o.value;
+        let me = subRateObject, subList=null;
+        let value = info.newValue;
+        let subRate = me.datas[info.row];
+        if(subRate.editable == true || subRate.isSub == true){//是可编辑的,要检查数据类型
+            let checkResult = scMathUtil.isNumOrFormula(value);
+            if(checkResult!=null && !isNaN(checkResult)){
+                value = scMathUtil.roundForObj(checkResult,getDecimal("feeRate"));
+            }else {
+                alert('当前输入的数据类型不正确,请重新输入。');
+                me.showSubRateData();
+                return;
+            }
+        }
+
+        if(subRate.isSub == true){//是树节点的子节点,计算父节点的值
+            let parentRate = _.find(me.datas,{"ID":subRate.ParentID});//找到父节点
+            if(parentRate){
+                let sum = 0;
+                subList = _.cloneDeep(parentRate.subList);
+                for(let s of subList){//按比例计算
+                    if(s.ID == subRate.ID) s.value = value;//当前项要用新输入的值
+                    let v_a = scMathUtil.roundForObj(s.value * s.amount,getDecimal("process"))
+                    sum = scMathUtil.roundForObj(sum + v_a,getDecimal("feeRate"));
                 }
-                selectValueList.push(selectMap[key]);
-            })
-            let mapID =selectValueList.join('-');
-            let rate = me.valueMap[mapID];
-            feeRateObject.updateBySelect(rate,selectMap,mapID);
+                value = sum;
+                subRate = parentRate;//把subRate 指向parentRate
+            }
+        } else if(subRate.subList && subRate.subList.length > 0){//输入树节结的父结点,子结点都等于父节点的值
+            subList = _.cloneDeep(subRate.subList);
+            for(let t of subList){
+                t.value = value
+            }
         }
+        feeRateObject.setRateFromSub(subRate,value,subList);
     },
 
     destorySpreadView:function () {

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

@@ -11,7 +11,7 @@ let zmhs_obj = {
         header: [
             {headerName: "调整", headerWidth: 35, dataCode: "isAdjust", dataType: "String", cellType: "checkBox"},
             {headerName: "条件", headerWidth: 180, dataCode: "name", dataType: "String", cellType: "button",getText:'forName'},
-            {headerName: "内容", headerWidth: 70, dataCode: "content", dataType: "String", hAlign: "left",getText:'forContent'}
+            {headerName: "内容", headerWidth: 70, dataCode: "content", dataType: "String", hAlign: "left",getText:'forContent',cellType:'tipsCell'}
         ],
         view: {
             lockColumns:[0,1,2],
@@ -36,7 +36,7 @@ let zmhs_obj = {
         },
         emptyRowHeader: true,
         autoFit:true,
-        fitRow:['name','content']
+        fitRow:['name']
     },
     cusSpread:null,
     cusSheet:null,
@@ -112,6 +112,7 @@ let zmhs_obj = {
         }
     },
     showCoeData:function (node) {
+        let preSelections = this.coeSheet.getSelections();
         let selected = node?node:projectObj.project.mainTree.selected;
         let ration_coe = projectObj.project.ration_coe;
         let coeList = [];
@@ -141,6 +142,9 @@ let zmhs_obj = {
         if(projectReadOnly){
             disableSpread(zmhs_obj.coeSpread);
         }
+        if(preSelections){//定位光标到之前的位置
+            this.coeSheet.setSelection(preSelections[0].row,preSelections[0].col,preSelections[0].rowCount,preSelections[0].colCount);
+        }
     },
     showCusData:function (node) {
         let selected = node?node:projectObj.project.mainTree.selected;

+ 12 - 11
web/building_saas/pm/html/project-management.html

@@ -60,21 +60,22 @@
     <%include ../../../common/html/header.html %>
 </div>
     <div class="main">
+        <a id="autoOpenTender" style="display: none;"></a>
         <div class="poj-manage container-fluid p-0">
             <div class="pm-side">
                 <div class="poj-cate">
-                    <div class="dropdown">
-                        <a class="btn dropdown-toggle" data-toggle="dropdown">
+                    <div class="dropdown" style="height: 38px">
+                        <!--<a class="btn dropdown-toggle" data-toggle="dropdown">
                             <i class="fa fa-search"></i>
                         </a>
                         <div class="dropdown-menu p-3" aria-labelledby="dropdownMenuButton">
                             <div class="form-group m-0">
                                 <input type="text" class="form-control form-control-sm" placeholder="搜索所有工程"style="width:300px">
                             </div>
-                        </div>
+                        </div>-->
                     </div>
                     <ul class="nav nav-pills flex-column" id="sideTab">
-                        <li class="nav-item" data-original-title="全部" data-placement="right" data-toggle="tooltip">
+                        <li class="nav-item" data-original-title="项目管理" data-placement="right" data-toggle="tooltip">
                             <a class="nav-link active" href="#pm_all" role="tab" id="tab_pm_all" data-toggle="tab"><i class="fa fa-bars"></i></a>
                         </li>
                         <!--<li class="nav-item" data-original-title="最近使用" data-placement="right" data-toggle="tooltip">
@@ -99,13 +100,13 @@
                 <div class="tab-content">
                     <div class="tab-pane active" id="pm_all" role="tabpanel">
                         <div class="toolsbar">
-                            <legend class="m-0 px-4 pb-1">全部
-                                <div class="tools-btn btn-group align-top px-3 ">
-                                    <div class="dropdown">
-                                        <a id="startA" class="btn btn-sm" href="javascript:void(0);" role="button" data-toggle="modal" aria-haspopup="true" aria-expanded="false">
-                                            新建
-                                        </a>
-                                    </div>
+                            <legend class="m-0 px-4">项目管理
+                                <div class="tools-btn btn-group align-top px-3 mt-2">
+                                    <a id="startA" href="javascript:void(0);" data-toggle="modal" data-target="#addPoj3" class="btn btn-sm"><i class="fa fa-sticky-note-o"></i> 新建</a>
+                                    <a id="upLevel" href="javascript:void(0);" class="btn btn-light btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
+                                    <a id="downLevel" href="javascript:void(0);" class="btn btn-light btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
+                                    <a id="upMove" href="javascript:void(0);" class="btn btn-light btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                                    <a id="downMove" href="javascript:void(0);" class="btn btn-light btn-sm" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
                                 </div>
                             </legend>
                         </div>

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

@@ -331,7 +331,8 @@ const gcTreeObj = {
             let centerY = (hitinfo.cellRect.y + offset + (hitinfo.cellRect.y + offset + hitinfo.cellRect.height)) / 2;;
             if (!node || node.children.length === 0) { return; }
 
-            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
+            if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 &&
+                hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) {
                 node.setExpanded(!node.expanded);
                 TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
                     let iCount = node.posterityCount(), i, child;

+ 171 - 21
web/building_saas/pm/js/pm_newMain.js

@@ -86,7 +86,7 @@ const projTreeObj = {
             allowContextMenu: false,
             allowCopyPasteExcelStyle : false,
             allowExtendPasteRange: false,
-            allowUserDragDrop : true,
+            allowUserDragDrop : false,
             allowUserDragFill: false,
             scrollbarMaxAlign : true,
             showDragDropTip:false
@@ -184,6 +184,7 @@ const projTreeObj = {
             this.bindEvent(newWorkBook);
             this.loadContextMenu();
             this.loadStartMenu();
+            this.loadBtn();
         }
         return newWorkBook;
     },
@@ -371,6 +372,142 @@ const projTreeObj = {
             }
         });
     },
+    //刷新按钮有效性(升降级、上下移)
+    refreshBtn: function (selected) {
+        const upLevel = $('#upLevel');
+        const downLevel = $('#downLevel');
+        const upMove = $('#upMove');
+        const downMove = $('#downMove');
+        if (!selected) {
+            upLevel.addClass('disabled');
+            downLevel.addClass('disabled');
+            upMove.addClass('disabled');
+            downMove.addClass('disabled');
+            return;
+        }
+        /* 升级有效
+         * 当前选中文件夹,且文件夹有父项,且父项是文件夹
+         * 当前选中建设项目,且建设项目有父项,且父项是文件夹
+         */
+        if ([projectType.project, projectType.folder].includes(selected.data.projType)
+            && selected.parent && selected.parent.data && selected.parent.data.projType === projectType.folder) {
+            upLevel.removeClass('disabled');
+        } else {
+            upLevel.addClass('disabled');
+        }
+        /*
+         * 降级有效
+         * 当前选中文件夹,且文件夹有前兄弟,且前兄弟是文件夹
+         * 当前选中建设项目,且建设项目有前兄弟,且前兄弟是文件夹
+         * */
+        if ([projectType.project, projectType.folder].includes(selected.data.projType)
+            && selected.preSibling() && selected.preSibling().data.projType === projectType.folder) {
+            downLevel.removeClass('disabled');
+        } else {
+            downLevel.addClass('disabled');
+        }
+        /*
+         * 上移有效
+         * 当前选中行有前兄弟,不论前兄弟类型
+         * */
+        selected.preSibling() ? upMove.removeClass('disabled') : upMove.addClass('disabled');
+        /*
+         * 后移有效
+         * 当前选中行有后兄弟,不论后兄弟类型
+         * */
+        selected.nextSibling ? downMove.removeClass('disabled') : downMove.addClass('disabled');
+
+    },
+    doAfterTreeOpr: function ({selected, parent, next, projectMap}) {
+        $.bootstrapLoading.start();
+        moveProjects({"user_id": userID, rootProjectID: null, projectMap: projectMap, feeRateMap: {}, unitPriceMap: {}},function (result) {
+            for (let key in result) {//更新前端节点数据
+                let updateData = result[key].update;
+                let node = projTreeObj.tree.findNode(result[key].query.ID);
+                if (node) {
+                    for (let ukey in updateData) {
+                        _.set(node.data,ukey,updateData[ukey]);
+                    }
+                }
+            }
+            projTreeObj.moveTo(selected, null, parent, next, null);
+            $.bootstrapLoading.end();
+        });
+    },
+    //升级后选中节点的后兄弟节点不成为其子节点,因为有层级类型限制(相当于选中节点移动到父项后成为其后兄弟)
+    upLevel: function () {
+        let selected = projTreeObj.tree.selected,
+            parent = selected.parent.parent,
+            next = selected.parent.nextSibling,
+            projectMap = {};
+        //更新父节点
+        projectMap[selected.pid()] = {query: {ID: selected.pid()}, update: {NextSiblingID: selected.id()}};
+        //更新选中节点前兄弟节点
+        let orgPre = selected.preSibling();
+        if (orgPre) {
+            projectMap[orgPre.id()] = {query: {ID: orgPre.id()}, update: {NextSiblingID: selected.nid()}};
+        }
+        //更新选中节点
+        projectMap[selected.id()] = {query: {ID: selected.id()}, update: {ParentID: selected.parent.pid(), NextSiblingID: selected.parent.nid()}};
+        this.doAfterTreeOpr({selected, parent, next, projectMap});
+    },
+    downLevel: function () {
+        let selected = projTreeObj.tree.selected,
+            parent = null,
+            next = null,
+            projectMap = {};
+        //更新前兄弟节点
+        let orgPre = selected.preSibling();
+        parent = orgPre;
+        projectMap[orgPre.id()] = {query: {ID: orgPre.id()}, update: {NextSiblingID: selected.nid()}};
+        //更新前兄弟最后子节点
+        if (orgPre.children.length > 0) {
+            let lastChild = orgPre.lastChild();
+            projectMap[lastChild.id()] = {query: {ID: lastChild.id()}, update: {NextSiblingID: selected.id()}};
+        }
+        //更新选中节点
+        projectMap[selected.id()] = {query: {ID: selected.id()}, update: {ParentID: orgPre.id(), NextSiblingID: -1}};
+        this.doAfterTreeOpr({selected, parent, next, projectMap});
+    },
+    upMove: function () {
+        let selected = projTreeObj.tree.selected,
+            parent = selected.parent,
+            next = selected.preSibling(),
+            projectMap = {};
+        //更新前前兄弟
+        let prepre = selected.preSibling().preSibling();
+        if (prepre) {
+            projectMap[prepre.id()] = {query: {ID: prepre.id()}, update: {NextSiblingID: selected.id()}};
+        }
+        //更新前兄弟
+        let pre = selected.preSibling();
+        projectMap[pre.id()] = {query: {ID: pre.id()}, update: {NextSiblingID: selected.nid()}};
+        //更新选中节点
+        projectMap[selected.id()] = {query: {ID: selected.id()}, update: {NextSiblingID: pre.id()}};
+        this.doAfterTreeOpr({selected, parent, next, projectMap});
+    },
+    downMove: function () {
+        let selected = projTreeObj.tree.selected,
+            parent = selected.parent,
+            next = selected.nextSibling.nextSibling,
+            projectMap = {};
+        //更新前兄弟
+        let pre = selected.preSibling();
+        if (pre) {
+            projectMap[pre.id()] = {query: {ID: pre.id()}, update: {NextSiblingID: selected.nid()}};
+        }
+        //更新后兄弟
+        projectMap[selected.nid()] = {query: {ID: selected.nid()}, update: {NextSiblingID: selected.id()}};
+        //更新选中节点
+        projectMap[selected.id()] = {query: {ID: selected.id()}, update: {NextSiblingID: selected.nextSibling.nid()}};
+        this.doAfterTreeOpr({selected, parent, next, projectMap});
+    },
+    loadBtn: function () {
+        $('#upLevel').click(this.upLevel.bind(this));
+        $('#downLevel').click(this.downLevel.bind(this));
+        $('#upMove').click(this.upMove.bind(this));
+        $('#downMove').click(this.downMove.bind(this));
+    },
     getSelStyle: function (backColor) {
         let style = new GC.Spread.Sheets.Style();
         style.backColor = backColor;
@@ -397,6 +534,7 @@ const projTreeObj = {
         let me = this;
         let node = me.tree.items[newSel.row];
         node = node ? node : null;
+        me.refreshBtn(node);
         //恢复底色
         if(oldSel){
             me.setSelStyle(oldSel, me.setting.style.defalutBackColor,sheet);
@@ -607,6 +745,17 @@ const projTreeObj = {
             }
         }
     },
+    openTender: function (node, timeoutTime) {
+        setTimeout(function () {
+            let newTab = window.open('about:blank');
+            BeforeOpenProject(node.data.ID, {'fullFolder': GetFullFolder(node.parent)}, function () {
+                let mainUrl = `/main?project=${node.data.ID}`;
+                CommonAjax.get(mainUrl, [], function () {
+                    newTab.location.replace(mainUrl); //不能后退
+                });
+            });
+        }, timeoutTime);
+    },
     getTreeNodeCell: function (tree) {
         let me = projTreeObj;
         let indent = 20;
@@ -784,24 +933,25 @@ const projTreeObj = {
             }
             if(hitinfo.sheet.name() === "projectSheet"){//只有项目管理界面才执行
                 //单项文件,进入造价书界面
-                 if(node.data.projType === projectType.tender && withingClickArea()){
-                    let timeoutTime = 200;
-                    if($('.slide-sidebar').hasClass('open')){
-                        timeoutTime = 500;
-                    }
-                    setTimeout(function () {
-                        let newTab = window.open('about:blank');
-                        BeforeOpenProject(node.data.ID, {'fullFolder': GetFullFolder(node.parent)}, function () {
-                            let mainUrl = `/main?project=${node.data.ID}`;
-                            CommonAjax.get(mainUrl, [], function () {
-                                newTab.location.replace(mainUrl); //不能后退
-                            });
-                        });
-                    }, timeoutTime);
+                if(node.data.projType === projectType.tender && withingClickArea()){
+                    /*let thisClick = Date.now(),
+                        open = false;
+                    if (this.preNode === node && this.preClick && thisClick - this.preClick <= 300) {
+                        open = true;*/
+                        let timeoutTime = 200;
+                        if($('.slide-sidebar').hasClass('open')){
+                            timeoutTime = 500;
+                        }
+                        projTreeObj.openTender(node, timeoutTime);
+                    /*}
+                    this.preClick = open ? null : thisClick;
+                    this.preNode = open ? null : node;*/
                 }
                 if (!node || node.children.length === 0) { return; }
             }
-            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
+            //统一改成方框外1像素内都有效
+            if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 &&
+                hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) {
                 node.setExpanded(!node.expanded);
                 TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
                     let iCount = node.posterityCount(), i, child;
@@ -2039,7 +2189,7 @@ function AddTenderItems(selected, projName, tenderName, property, callback){
                     }
                 });
                 let pojNode = projTreeObj.insert(projData, parent, next);
-                projTreeObj.insert(tenderData, pojNode, null);
+                let tenderNode = projTreeObj.insert(tenderData, pojNode, null);
                 callback();
             });
         });
@@ -2056,12 +2206,13 @@ function AddTenderItems(selected, projName, tenderName, property, callback){
                 updateDatas.push({updateType: 'update', updateData: {ID: pre.id(), NextSiblingID: tenderID}});
             }
             UpdateProjectData(updateDatas, function (datas) {
+                let tenderNode = null;
                 datas.forEach(function (data) {
                     if(data.updateType === 'new') {
                         setInitSummaryData(data.updateData);
                         data.updateData.feeStandardName = data.updateData.property.feeStandardName || '';
                         data.updateData.valuationType = data.updateData.property.valuationType === 'bill' ? '预算' : '工程量清单';
-                        projTreeObj.insert(data.updateData, tempProj, null);
+                        tenderNode = projTreeObj.insert(data.updateData, tempProj, null);
                     }
                 });
                 callback();
@@ -2444,8 +2595,8 @@ function AddTender() {
 
 
         let calcProgramName = $('#tender-calcProgram').children("option:selected").text();
-
-        let callback = function() {
+        //let newTab = window.open('about:blank');
+        let callback = function(tenderNode) {
             $('#add-tender-confirm').removeClass('disabled');
             $("#add-tender-dialog").modal("hide");
             $('#tender-name').val('');
@@ -2454,7 +2605,6 @@ function AddTender() {
             $("#tender-calcProgram").children("option").removeAttr("selected");
             $("#poj-name").val('');
             $("#poj-name-info").hide();
-
         };
         let selectedItem = projTreeObj.tree.selected;
         //地区

+ 2 - 1
web/building_saas/pm/js/pm_share.js

@@ -372,7 +372,8 @@ const pmShare = (function () {
                 });
             }
             if (!node || node.children.length === 0) { return; }
-            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
+            if (hitinfo.x >= centerX - halfBoxLength - 2 && hitinfo.x <= centerX + halfBoxLength + 2 &&
+                hitinfo.y >= centerY - halfBoxLength - 2 && hitinfo.y <= centerY + halfBoxLength + 2) {
                 node.setExpanded(!node.expanded);
                 TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
                     let iCount = node.posterityCount(), i, child;