瀏覽代碼

Merge branch 'master' of http://192.168.1.12:3000/SmartCost/ConstructionCost

TonyKang 7 年之前
父節點
當前提交
64a9613fa6
共有 29 個文件被更改,包括 1104 次插入237 次删除
  1. 13 9
      config/config.js
  2. 1 1
      config/db/db_manager.js
  3. 2 2
      modules/glj/controllers/glj_controller.js
  4. 37 0
      modules/glj/models/mix_ratio_model.js
  5. 21 7
      modules/glj/models/unit_price_model.js
  6. 1 1
      modules/main/facade/bill_facade.js
  7. 1 1
      modules/pm/controllers/pm_controller.js
  8. 3 1
      modules/pm/models/project_model.js
  9. 53 1
      web/building_saas/css/main.css
  10. 21 13
      web/building_saas/fee_rates/fee_rate.html
  11. 4 4
      web/building_saas/glj/js/project_glj.js
  12. 4 1
      web/building_saas/js/global.js
  13. 1 1
      web/building_saas/main/html/main.html
  14. 34 22
      web/building_saas/main/js/models/fee_rate.js
  15. 18 6
      web/building_saas/main/js/models/installation_fee.js
  16. 2 0
      web/building_saas/main/js/models/project_glj.js
  17. 2 1
      web/building_saas/main/js/models/ration.js
  18. 35 10
      web/building_saas/main/js/views/calc_base_view.js
  19. 11 7
      web/building_saas/main/js/views/calc_program_manage.js
  20. 108 33
      web/building_saas/main/js/views/fee_rate_view.js
  21. 12 1
      web/building_saas/main/js/views/glj_view.js
  22. 33 7
      web/building_saas/main/js/views/installation_fee_view.js
  23. 3 1
      web/building_saas/main/js/views/project_view.js
  24. 74 1
      web/building_saas/main/js/views/sub_fee_rate_views.js
  25. 4 17
      web/building_saas/pm/html/project-management-Recycle.html
  26. 6 6
      web/building_saas/pm/html/project-management.html
  27. 456 14
      web/building_saas/pm/js/pm_gc.js
  28. 144 68
      web/building_saas/pm/js/pm_newMain.js
  29. 0 1
      web/building_saas/pm/js/pm_tree.js

+ 13 - 9
config/config.js

@@ -1,15 +1,19 @@
 module.exports = {
     current: {server: "192.168.1.184", port: "60666",redis:{server:'192.168.1.184',port:'6379',pwd:'smartCost'}},
     local: {server: "localhost", port: "27017"},
-    qa: {server: "192.168.1.184", port: "60666", options:{
-        user:'smartcost',
-        pass:'smartcost3850888',
-        auth: {
-            "authdb": "admin"
-        },
-        connectTimeoutMS: 20000,
-        useMongoClient: true
-    }},
+    qa: {
+        server: "192.168.1.184",
+        port: "60666",
+        options:{
+            user:'smartcost',
+            pass:'smartcost3850888',
+            auth: {
+                "authdb": "admin"
+              },
+            connectTimeoutMS: 20000,
+            useMongoClient: true
+        }
+    },
     test_auth: {
             server: "120.78.150.216",
             port: "27017",

+ 1 - 1
config/db/db_manager.js

@@ -48,7 +48,7 @@ module.exports = {
     },
     connect:function (env="local") {
         var config = require("../config.js");
-        var dbURL = 'mongodb://' + config.current.server + ":" + config.current.port + '/scConstruct';
+        var dbURL = 'mongodb://' + config[env].server + ":" + config[env].port + '/scConstruct';
         if(config[env].options){
             mg.connect(dbURL,config[env].options);
         }else {

+ 2 - 2
modules/glj/controllers/glj_controller.js

@@ -325,7 +325,7 @@ class GLJController extends BaseController {
 
             // 查找对应单价文件的项目工料机数据
             let unitPriceModel = new UnitPriceModel();
-            let copyResult = await unitPriceModel.copyNotExist(currentUnitPriceId, targetUnitPriceFile.id);
+            let copyResult = await unitPriceModel.copyNotExist(currentUnitPriceId, targetUnitPriceFile.id,projectId);
             // 复制成功后更改project数据
             if (!copyResult) {
                 throw '复制数据失败';
@@ -385,7 +385,7 @@ class GLJController extends BaseController {
 
             // 查找对应单价文件的项目工料机数据
             let unitPriceModel = new UnitPriceModel();
-            let copyResult = await unitPriceModel.copyNotExist(currentUnitPriceId, addResult.id);
+            let copyResult = await unitPriceModel.copyNotExist(currentUnitPriceId, addResult.id,projectId);
             // 复制成功后更改project数据
             if (!copyResult) {
                 throw '复制数据失败';

+ 37 - 0
modules/glj/models/mix_ratio_model.js

@@ -79,6 +79,43 @@ class MixRatioModel extends BaseModel {
         return result.ok !== undefined && result.ok === 1;
     }
 
+    //复制组成物到切换后的组成物映射表
+    async copyNotExist(currentUnitPriceId, changeUnitPriceId,gljMap){
+        let currentMap = {},targetMap = {}, insertData = [];
+        //取原单价文件所有的的组成物
+        let currentList = await  this.db.find({'unit_price_file_id':currentUnitPriceId});
+        // 过滤mongoose格式
+        currentList = JSON.stringify(currentList);
+        currentList = JSON.parse(currentList);
+        this.getConnectionMap(currentMap,currentList);
+
+        //切换后的单价文件所有的的组成物
+        let targetList = await this.db.find({'unit_price_file_id':changeUnitPriceId});
+        this.getConnectionMap(targetMap,targetList);
+        for(let ckey in currentMap){
+            if(targetMap[ckey]){//如果切换后的单价文件已经存在,则不用复
+                continue;
+            }
+            if(gljMap[ckey]){//在本项目中有用到
+                for(let ratio of  currentMap[ckey]){
+                    delete ratio._id;  // 删除原有id信息
+                    delete ratio.id;
+                    ratio.unit_price_file_id = changeUnitPriceId;
+                    insertData.push(ratio);
+                }
+            }
+        }
+        return insertData.length > 0 ? this.add(insertData) : true;
+    }
+    getConnectionMap(map,list){
+        for(let l of list){
+            if(map[l.connect_key]){
+                map[l.connect_key].push(l);
+            }else {
+                map[l.connect_key] = [l];
+            }
+        }
+    }
 }
 
 export default MixRatioModel;

+ 21 - 7
modules/glj/models/unit_price_model.js

@@ -14,6 +14,8 @@ import _ from "lodash";
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
 let collectionName = 'unit_price';
 let decimal_facade = require('../../main/facade/decimal_facade');
+let gljListModel = mongoose.model("glj_list");
+
 
 class UnitPriceModel extends BaseModel {
 
@@ -329,7 +331,7 @@ class UnitPriceModel extends BaseModel {
      * @param {Number} changeUnitPriceId
      * @return {Promise}
      */
-    async copyNotExist(currentUnitPriceId, changeUnitPriceId) {
+    async copyNotExist(currentUnitPriceId, changeUnitPriceId,projectId) {
         let result = false;
         // 首先查找原单价文件id下的数据
         let currentUnitList = await this.findDataByCondition({unit_price_file_id: currentUnitPriceId}, null, false);
@@ -340,6 +342,13 @@ class UnitPriceModel extends BaseModel {
         currentUnitList = JSON.stringify(currentUnitList);
         currentUnitList = JSON.parse(currentUnitList);
 
+        let gljList = await gljListModel.find({'project_id':projectId});
+        let gljMap = {};//用来记录glj的映射表,本项目有使用的工料机才需要copy过去
+        for(let g of gljList){
+            let g_index = this.getIndex(g,['code','name','specs','unit','type']);
+            gljMap[g_index] = g;
+        }
+
         let codeList = [];
         let nameList =[];
         for (let tmp of currentUnitList) {
@@ -364,13 +373,18 @@ class UnitPriceModel extends BaseModel {
             if (targetUnitList !== null && targetUnitList[t_index] !== undefined) {
                 continue;
             }
-            // 删除原有id信息
-            delete tmp._id;
-            delete tmp.id;
-            tmp.unit_price_file_id = changeUnitPriceId;
-            insertData.push(tmp);
+            if(gljMap[t_index]){//如果本项目有用到才复制
+                delete tmp._id;  // 删除原有id信息
+                delete tmp.id;
+                tmp.unit_price_file_id = changeUnitPriceId;
+                insertData.push(tmp);
+            }
         }
-        return insertData.length > 0 ? this.add(insertData) : true;
+        let uResult = insertData.length > 0 ? this.add(insertData) : true;
+        let mixRatioModel = new MixRatioModel();
+        let mResult = await mixRatioModel.copyNotExist(currentUnitPriceId, changeUnitPriceId,gljMap);//复制组成物
+        return uResult&&mResult;
+
     }
 
 

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

@@ -3,7 +3,7 @@
  */
 let mongoose = require('mongoose');
 let quantity_detail = require("./quantity_detail_facade");
-let Bills_Lib = mongoose.model('std_bills_lib_list');
+let Bills_Lib = mongoose.model('std_bills_lib_bills');
 let bill_Model = require('../models/bills').model;
 let _ = require("lodash");
 module.exports={

+ 1 - 1
modules/pm/controllers/pm_controller.js

@@ -125,7 +125,7 @@ module.exports = {
     },
     copyProjects: function (req, res) {
         let data = JSON.parse(req.body.data);
-        ProjectsData.copyUserProjects(req.session.sessionUser.ssoId, data.updateData, function (err, message, data) {
+        ProjectsData.copyUserProjects(req.session.sessionUser.ssoId, req.session.sessionCompilation._id, data.updateData, function (err, message, data) {
             if (err === 0) {
                 callback(req, res, err, message, data);
             } else {

+ 3 - 1
modules/pm/models/project_model.js

@@ -287,7 +287,7 @@ ProjectsDAO.prototype.udpateUserFiles = async function (userId, datas, callback)
     }
 };
 
-ProjectsDAO.prototype.copyUserProjects = function (userId, datas, callback) {
+ProjectsDAO.prototype.copyUserProjects = function (userId, compilationId, datas, callback) {
     let data, project, updateLength = 0, hasError = false, deleteInfo = null, tempType = 1, i;
     let updateAll = function (err) {
         if (!err) {
@@ -306,7 +306,9 @@ ProjectsDAO.prototype.copyUserProjects = function (userId, datas, callback) {
             if (data.updateType === 'update') {
                 Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll)
             } else if (data.updateType === 'copy') {
+                console.log(userId);
                 data.updateData['userID'] = userId;
+                data.updateData['compilation'] = compilationId;
                 data.updateData['createDateTime'] = new Date();
                 let newProject = new Projects(data.updateData);
                 newProject['srcProjectId'] = data.srcProjectId;

+ 53 - 1
web/building_saas/css/main.css

@@ -33,6 +33,13 @@ body {
     width:100%;
     z-index: 999
 }
+/*add*/
+.in-1{padding-left:0px!important}
+.in-2{padding-left:21px!important}
+.in-3{padding-left:42px!important}
+.in-4{padding-left:63px!important}
+.in-5{padding-left:84px!important}
+.in-6{padding-left:105px!important}
 .main {
     position: relative;
     background: #f7f7f9;
@@ -66,6 +73,7 @@ body {
 .main-nav .nav-tabs{
     border-bottom: none
 }
+
 .poj-manage .col-auto{
     background:#f7f7f9
 }
@@ -96,7 +104,7 @@ body {
     margin-left: 29px;
     background: #fff
 }
-.toolsbar,.toolsbar-f {
+.toolsbar,.toolsbar-f,.toolsbar_feeRate {
     border-bottom: 1px solid #ccc
 }
 .tools-btn {
@@ -269,6 +277,16 @@ body {
 .poj-list, .side-content ,.form-view{
     overflow: auto;
 }
+/*add*/
+.poj-list span.poj-icon {
+    padding-right:7px;
+    color:#ccc
+}
+/*add*/
+.poj-list a.tree-open,.poj-list a.tree-close{
+    width:15px;
+    display: inline-block;
+}
 .print-toolsbar{
     padding:5px
 }
@@ -331,6 +349,40 @@ body {
 .dropdown-item.disabled, .dropdown-item:disabled{
     pointer-events:none
 }
+/*add*/
+.text-green{
+    color: #172a30
+}
+/*add*/
+label.title{
+    display: inline-block;
+    width: 100px;
+}
+/*add*/
+.modal-feeRate {max-width: 550px}
+/*add*/
+.gc-column-header-cell{
+    text-align: center!important;
+}
+/*add*/
+div.resize{
+    height: 4px;
+    background: #f7f7f9;
+    width: 100%;
+    cursor: s-resize;
+}
+/*add*/
+.zlfb-check{
+    margin-left: 0;
+}
+/*add*/
+legend.legend{
+    display:block;
+    width:auto;
+    font-size:0.9rem;
+    top:-15px;
+    background: white;
+}
 .tools-symbol{
     width:450px
 }

+ 21 - 13
web/building_saas/fee_rates/fee_rate.html

@@ -1,27 +1,35 @@
 
 
 <div >
-<div class="toolsbar px-1">
+<div class="toolsbar_feeRate px-1 ">
     <div class="form-inline py-1">
         <label class="mx-2" >当前使用:<span id="feeRateFileName">费率1</span>(<a href="#" id="pop-lv"><span id="projectCount">3</span> 单位工程使用</a>)
             <a class="btn btn-sm ml-1" href="#" data-toggle="modal" data-target="#change-lv" id="changFeeRateFile"><i class="fa fa-exchange"></i> 选择其他</a>
             <a class="btn btn-sm ml-1" href="#" data-toggle="modal" id="saveAs" data-target="#copy-lv"><i class="fa fa-files-o"></i> 另存单独用</a></label>
     </div>
 </div>
-<div class="container-fluid">
-        <div class="row">
-            <div class="main-content col-lg-8 p-0">
-                <div class="form-inline py-1">
-                    <label class="mx-2" >基于&nbsp;&nbsp;<span id="feeRateLibName">重庆渝建发[2016]35号</span></label>
-                    <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 class=" grid  main-data-full-fl" id="divFee"></div>
-            </div>
-            <div class="col-lg-4 py-1">
-                <div class="py-1"><input type="checkbox" id="cascadeSet" checked >统一设置相同参数</div>
-                <div class="grid  main-data-full-fl" id="subRate"></div>
+<div class="toolsbar_feeRate px-1">
+    <div class="row" style="margin-left: 0px">
+        <div class="col-lg-8 p-0">
+            <div class="form-inline py-1">
+                <label class="mx-2" >基于&nbsp;&nbsp;<span id="feeRateLibName">重庆渝建发[2016]35号</span></label>
+                <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="form-inline py-1" style="margin-top: 5px"><input type="checkbox" id="cascadeSet" checked >  <label class="mx-2" >统一设置相同参数</label></div>
+        </div>
+    </div>
+</div>
+<div class="container-fluid">
+    <div class="row ">
+        <div class="col-lg-8 p-0 ">
+            <div class="grid main-data-full-feeRate" id="divFee"></div>
+        </div>
+        <div class="col-lg-4 p-0">
+            <div class="grid main-data-full-feeRate" id="subRate"></div>
+        </div>
+    </div>
 </div>
 <!--弹出更换-->
 <div class="modal fade" id="change-lv" data-backdrop="static">

+ 4 - 4
web/building_saas/glj/js/project_glj.js

@@ -35,9 +35,9 @@ $(document).ready(function () {
         init();
     });
 
-    slideResize($("#glj-main"), function () {
+ /*   slideResize($("#glj-main"), function () {
         projectGLJSpread.sheetObj.spread.refresh();
-    });
+    });*/
 
     // 单价文件切换弹框
     $('#change-dj').on('shown.bs.modal', function () {
@@ -267,9 +267,9 @@ function spreadInit() {
         }
     });*/
 
-    loadSize("glj-main", function () {
+  /*  loadSize("glj-main", function () {
         projectGLJSpread.sheetObj.spread.refresh();
-    });
+    });*/
 }
 
 /**

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

@@ -3,14 +3,17 @@ function autoFlashHeight(){
     var headerHeight = $(".header").height();
     var toolsbarHeight = $(".toolsbar").height();
     var ftoolsbarHeight = $(".toolsbar-f").height();
+   // var feeRateToolsbarHeight = $(".toolsbar_feeRate").height();
     var bottomContentHeight = $(".bottom-content").height();
     var toolsBarHeightQ = $(".tools-bar-height-q").height();
     var toolsBarHeightD = $(".tools-bar-height-d").height();
     $(".main-data-side-q").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightQ-302);
     $(".main-data-side-d").height($(window).height()-headerHeight-toolsbarHeight-toolsBarHeightD-302);
     $(".main-data-top").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
+    $("#project_glj_sheet").height($(window).height()-headerHeight-toolsbarHeight-bottomContentHeight-1);
     $(".main-data-full").height($(window).height()-headerHeight-toolsbarHeight-1);
     $(".main-data-full-fl").height($(window).height()-headerHeight-toolsbarHeight-37);
+    $(".main-data-full-feeRate").height($(window).height()-headerHeight-78);
     $(".main-data-not").height($(window).height()-headerHeight-1);
     $(".main-data-side-search").height($(window).height()-headerHeight-toolsbarHeight-64);
     $(".side-content").height($(window).height()-headerHeight );
@@ -19,9 +22,9 @@ function autoFlashHeight(){
     $(".form-list").height($(window).height()-headerHeight-50 );
 
 };
-$(window).resize(autoFlashHeight);
 /*全局自适应高度结束*/
 $(function () {
+    $(window).resize(autoFlashHeight);
     /*侧滑*/
   /*  $(".open-sidebar").click(function () {
         $(".slide-sidebar").animate({width: "800"}).addClass("open");

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

@@ -1175,7 +1175,7 @@
         <!-- endinject -->
 
         <script type="text/javascript">
-            autoFlashHeight();
+            //autoFlashHeight();
         </script>
 
         <SCRIPT type="text/javascript">

+ 34 - 22
web/building_saas/main/js/models/fee_rate.js

@@ -144,11 +144,12 @@ var FeeRate = {
             var errCallBack=function () {
                 me.dataRecovery();
                 $.bootstrapLoading.end();
-            }
+            };
+            $.bootstrapLoading.start();
             CommonAjax.post('/feeRates/updateRates', data, function (result) {
                 _.forEach(items,function (t) {
-                     feeRateObject.mainViews.data.updateItem(t.rateIndex,t.rate);
-                 })
+                    feeRateObject.mainFeeRateSheet.setValue(t.rateIndex, 1, t.rate.rate);
+                 });
                  me.onFeeRateFileChange();
                 $.bootstrapLoading.end();
             },errCallBack);
@@ -370,10 +371,7 @@ var FeeRate = {
                         if(data.hasOwnProperty('feeRate')){
                             rate.rate=fee_value;
                             me.onFeeRateChange(rate.ID,fee_value);
-                        }/*else {
-                            bill.feeRate=value;
-                            projectObj.mainController.refreshTreeNode([node])
-                        }*/
+                        }
                     });
                 }else {
                     projectObj.mainController.refreshTreeNode([node]);
@@ -385,7 +383,7 @@ var FeeRate = {
             var value= number_util.checkNumberValue(value,getDecimal("feeRate"));
             if(value){
                 if(editInfo.calcItem.feeRateID){
-                    var rate = projectObj.project.FeeRate.getFeeRateByID(editInfo.calcItem.feeRateID);
+                    var rate = this.getFeeRateByID(editInfo.calcItem.feeRateID);
                     if(rate!=undefined){
                         this.updateFeeRateByCalc(rate,value);
                         return;
@@ -407,20 +405,34 @@ var FeeRate = {
         };
         FeeRate.prototype.updateFeeRateByCalc=function (rate,value) {
             var me=this;
-            var data={
-                query:{
-                    'ID':this.getActivateFeeRateID(),
-                    'rates.ID':rate.ID
-                },
-                doc:{
-                    'rates.$.rate':value
-                }
-            }
-            CommonAjax.post('/feeRates/updateFeeRate', data, function (data) {
-                rate.rate=value;
+            me.updateFeeRateByID(rate.ID,{'rate':value},function () {
                 me.onFeeRateChange(rate.ID,value);
-            });
-        }
+            })
+        };
+
+        FeeRate.prototype.updateFeeRateByID = function (rateID,doc,callback) {
+          let me = this,preKey = 'rates.$.';
+          let data = {
+              query:{
+                  'ID':me.getActivateFeeRateID(),
+                  'rates.ID':rateID
+              },
+              doc:{}
+          };
+          for(let prop in doc){//做了个转换,加上前缀
+            data.doc[preKey+prop] = doc[prop];
+          }
+          CommonAjax.post('/feeRates/updateFeeRate', data, function (data) {
+              //更新缓存
+              let rate = me.getFeeRateByID(rateID);
+              for(let dkey in doc){
+                  rate[dkey] = doc;
+              }
+            if(callback){
+                callback();
+            }
+          });
+        };
 
         FeeRate.prototype.getfbUpdateData=function (rate,bill,value,editText) {
             var data=null;
@@ -486,7 +498,7 @@ var FeeRate = {
                             feeRateID:rate.ID
                         }
                     }
-                }
+                };
             this.setFeeRateToBill(data,callback);
         };
 

+ 18 - 6
web/building_saas/main/js/models/installation_fee.js

@@ -57,28 +57,40 @@ var installation_fee = {
             let installationFee = this.getInstallationFeeByLibID(libID);
             return _.find(installationFee.feeRule,{'ID':feeRuleID});
         };
-        installation_fee.prototype.updateFeeItem = function(doc,libID,feeItemID,callback){
+        installation_fee.prototype.updateFeeItem = function(doc,libID,feeItemID,cleanPosition,callback){
             let me = this,ration_install=projectObj.project.ration_installation;
             let feeItem = me.getFeeItemByID(libID,feeItemID);
             let temFeeItem = _.cloneDeep(feeItem);//暂时不更新缓存
             let updateData = [];
+            let cleanRules = [];
             let rationInstallations = [];
             for(let d_key in doc){
                 temFeeItem[d_key] = doc[d_key]
             }
             updateData.push(me.getFeeItemUpdateData(libID,feeItemID,doc));
-            if(temFeeItem.isCal == 1){//勾选记取的时候要同步更新对应的定额安装费
-                let sections = me.getInstallSectionsByfeeItemID(libID,feeItemID);
-                for (let s of sections){
+            let sections = me.getInstallSectionsByfeeItemID(libID,feeItemID);
+            for (let s of sections){
+                if(temFeeItem.isCal == 1){//勾选记取的时候要同步更新对应的定额安装费
                     me.getRIUpdateDataBySectionUpdate(s.ID,s.feeRuleId,rationInstallations);//生成受影响的定额安装增加费并加入到数组中
+                }else {//取消打勾时清空对应的定额安装费的规则项
+                    me.getRIUpdateDataBySectionUpdate(s.ID,"",rationInstallations);//生成受影响的定额安装增加费并加入到数组中
                 }
             }
+            if(cleanPosition==true){//如果要清除记取位置
+                let [dataArray,impacRules] = installationFeeObj.getFeeRuleUpdateDataByFeeItem(feeItem,{code: "",ID:''});
+                updateData = updateData.concat(dataArray);
+                cleanRules = impacRules;
+            }
             $.bootstrapLoading.start();
             me.submitInstallationUpdate(updateData,rationInstallations,function (data) {
                 //更新缓存
                 for(let d_key in doc){
                     feeItem[d_key] = doc[d_key]
                 }
+                for(let ir of cleanRules){//清除记取位置
+                    ir.position = "";
+                    ir.billID  = "";
+                }
                 if(callback){
                     callback();
                 }
@@ -621,7 +633,7 @@ var installation_fee = {
                     'JXFTZ':{
                         rationID:data.ID,
                         billsItemID:data.billsItemID,
-                        shortName:project.projectGLJ.getShortNameByID(gljType.MACHINE_COMPOSITION),
+                        shortName:project.projectGLJ.getShortNameByID(gljType.GENERAL_MACHINE),
                         GLJID:-1,
                         projectID:data.projectID,
                         code:'JXFTZ',
@@ -629,7 +641,7 @@ var installation_fee = {
                         name:'机械费调整',
                         specs:'',
                         unit:'元',
-                        type:gljType.MACHINE_COMPOSITION,
+                        type:gljType.GENERAL_MACHINE,
                         basePrice:1,
                         adjCoe:null,
                         from:'std',

+ 2 - 0
web/building_saas/main/js/models/project_glj.js

@@ -323,6 +323,8 @@ ProjectGLJ.prototype.getRatioData=function(id,callback){
             if(callback){
                 callback(ratios);
             }
+        },function () {//取不到组成物的情况
+            callback([]);
         })
     }else {
         if(callback){

+ 2 - 1
web/building_saas/main/js/models/ration.js

@@ -403,11 +403,12 @@ var Ration = {
                        //添加新的记录
                        project.ration_glj.addDatasToList(recode.ration_gljs);
                        project.ration_coe.addDatasToList(recode.ration_coes);
+                       project.ration_installation.addDatasToList(recode.ration_installs);
                        //to do 添加增加安装费
                    }
                 }
                 project.projectGLJ.loadData(function () {
-                    gljOprObj.refreshView();
+                    gljOprObj.showDataIfRationSelect(projectObj.project.mainTree.selected,'11111');
                     project.calcProgram.calcRationsAndSave(refershNodes);
                     projectObj.mainController.refreshTreeNode(refershNodes, true);
                     $.bootstrapLoading.end();

+ 35 - 10
web/building_saas/main/js/views/calc_base_view.js

@@ -114,7 +114,11 @@ let calcBaseView = {
             if(!me.isDef(v)){
                 return;
             }
-            let baseFigure = `{${v}}`;
+            let baseFigure = '';
+            if(me.curType == me.type.bills)
+                baseFigure = `{${v}}`
+            else if (me.curType == me.type.ration)
+                baseFigure = `[${v}]`;
             if(baseFigure.trim() !== ''){
                 //在光标后面插入
                 let insertStr = me.insertStr(baseFigure);
@@ -161,7 +165,7 @@ let calcBaseView = {
         let me = calcBaseView;
         let showDatas;
         me.curType = type;
-        if(type === me.type.bills){//bills
+        if (type === me.type.bills) {
             //显示清单基数分类
             $('#cbClassList').show();
             $('#qd-jsjs .modal-content').css('width', '670px');
@@ -170,7 +174,7 @@ let calcBaseView = {
             //
             let node = projectObj.project.mainTree.selected;
             //输入框显示原本的
-            if(me.isDef(node.data.calcBase)){
+            if (me.isDef(node.data.calcBase)) {
                 me.inputExpr.val(cbParser.toFExpr(node.data.calcBase));
             }
             let baseObj = projectObj.project.calcBase.getBaseByClass(node);
@@ -178,24 +182,28 @@ let calcBaseView = {
             $('#cbClassList li .btn ').removeClass('btn btn-outline-secondary btn-sm active');
             $('#cb_ALL').addClass('btn btn-outline-secondary btn-sm active');
         }
-        else{//ration
+        else if (type == me.type.ration) {
             //去除清单基数分类
             $('#cbClassList').hide();
             $('#qd-jsjs .modal-content').css('width', '');
             $('#cbRowDiv').removeClass('row');
             $('#billsBaseSpread').removeClass('col-9');
 
+            let calcItem = calcProgramManage.getSelectionInfo().calcItem;
+            if (calcItem.dispExprUser) {
+                me.inputExpr.val(calcItem.dispExprUser);
+            }
             let bnArr = Object.keys(rationCalcBases);
             let baseArr = [];
-            for (let bn of bnArr){
-                 baseArr.push({base: bn})
+            for (let bn of bnArr) {
+                baseArr.push({base: bn})
             };
             showDatas = baseArr;
         }
+
         me.buildSheet();
         me.showData(showDatas);
         $('#qd-jsjs').modal('show');
-
     },
 
     getInputExpr: function () {
@@ -262,9 +270,26 @@ let calcBaseView = {
                     $('#qd-jsjs').modal('hide');
                 }
             }
-            //ration
-            else{
-
+            else if (me.curType === me.type.ration) {
+                let calcItem = calcProgramManage.getSelectionInfo().calcItem;
+                if (calcItem.dispExprUser != me.inputExpr.val()){
+                    calcItem.dispExprUser = me.inputExpr.val();
+                    calcItem.dispExpr = me.inputExpr.val();
+                    let data = {
+                        'projectID': projectObj.project.ID(),
+                        'templatesID': calcProgramManage.getSelectionInfo().template.ID,
+                        'calcItem': calcItem
+                    };
+                    calcProgramManage.saveCalcItem(data, function (rst) {
+                        if (rst){
+                            projectObj.project.calcProgram.calcAllNodesAndSave();
+                            calcProgramManage.refreshDetailSheet();
+                            $('#qd-jsjs').modal('hide');
+                        }
+                    });
+                }
+                else
+                    $('#qd-jsjs').modal('hide');
             }
         });
     },

+ 11 - 7
web/building_saas/main/js/views/calc_program_manage.js

@@ -60,14 +60,14 @@ let calcProgramManage = {
 
         me.mainSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onMainEnterCell);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.CellChanged, me.onDetailCellChanged);
-        me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EditEnded, me.onEditEnded);
+        me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EditEnded, me.onDetailEditEnded);
         let mSheet = me.mainSpread.getSheet(0);
         sheetCommonObj.showData(mSheet, me.mainSetting, me.datas);
 
         let dSheet = me.detailSpread.getSheet(0);
+        dSheet.name('calc_detail');
         feeRateObject.setFeeRateCellCol(dSheet,_.findIndex(me.detailSetting.header,{'dataCode':'feeRate'}));
         dSheet.getRange(-1, _.findIndex(me.detailSetting.header, {'dataCode': 'dispExprUser'}), -1, 1).cellType(calcBaseView.getCalcBaseCellType('ration'));
-        dSheet.name('calc_detail');
         sheetCommonObj.showData(dSheet, me.detailSetting, me.datas[0].calcItems);
     },
     onMainEnterCell: function(sender, args) {
@@ -81,21 +81,25 @@ let calcProgramManage = {
         sheetCommonObj.showData(dSheet, me.detailSetting, dData);
         me.detailSpread.resumePaint();
     },
-    onEditEnded: function(sender, args) {
+    onDetailEditEnded: function(sender, args) {
         $.bootstrapLoading.start();
 
         let me = calcProgramManage;
         let editInfo= me.getSelectionInfo();
-        if(me.detailSetting.header[args.col].dataCode == 'feeRate'){
+        if (me.detailSetting.header[args.col].dataCode == 'feeRate') {
             projectObj.project.FeeRate.updateFeeRateFromCalc(args.editingText,editInfo);
-        }else {
-            if(me.detailSetting.header[args.col].dataCode == 'displayFieldName'){
+        }
+        else {
+            if (me.detailSetting.header[args.col].dataCode == 'displayFieldName') {
                 if (editInfo.calcItem.displayFieldName == args.editingText) {
                     $.bootstrapLoading.end();
                     return;
                 }
                 editInfo.calcItem.fieldName = projectObj.project.calcProgram.compiledFeeTypeMaps[args.editingText];
                 editInfo.calcItem.displayFieldName = args.editingText;    // 这句不入库,仅用于切换后再切换回来时界面正确显示
+            }
+            else if (me.detailSetting.header[args.col].dataCode == 'dispExprUser'){  // 除非直接改单元格,弹窗不会走这里
+                alert(editInfo.calcItem.dispExprUser);
             };
 
             let data = {
@@ -142,7 +146,7 @@ let calcProgramManage = {
     },
     refreshDetailSheet:function () {
         var me=this;
-        if(me.mainSpread&&me.detailSpread){
+        if(me.mainSpread && me.detailSpread){
             var mainSheetIndex = me.mainSpread.getActiveSheet().getActiveRowIndex();
             sheetCommonObj.showData(me.detailSpread.getSheet(0), me.detailSetting,me.datas[mainSheetIndex].calcItems);
         }

+ 108 - 33
web/building_saas/main/js/views/fee_rate_view.js

@@ -5,6 +5,19 @@
 
 
 var feeRateObject={
+    mainFeeRateSpread:null,
+    mainFeeRateSheet:null,
+    mainFeeRateData:null,
+    mainFeeRateSetting:{
+        header: [
+            {headerName: "专业名称", headerWidth: 550, dataCode: "name", dataType: "String"},
+            {headerName: "值%", headerWidth: 250, dataCode: "rate", dataType: "Number",hAlign: "right",decimalField:"feeRate"},
+            {headerName: "备注", dataCode: "memo", dataType: "String"}
+        ],
+        view: {
+            lockColumns: [0]
+        }
+    },
     mainViews:null,
     datas:null,
     datasBackup:null,
@@ -19,7 +32,7 @@ var feeRateObject={
     sheetSetting: {
         header: [
             {headerName: "专业名称", headerWidth: 200, dataCode: "name", dataType: "String"},
-            {headerName: "值%", headerWidth: 150, dataCode: "rate", dataType: "Number",hAlign: "right",decimalField:"feeRate"},
+            {headerName: "值%", headerWidth: 120, dataCode: "rate", dataType: "Number",hAlign: "right",decimalField:"feeRate"},
             {headerName: "备注", dataCode: "memo", dataType: "String"}
         ],
         view: {
@@ -124,10 +137,7 @@ var feeRateObject={
         feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellClick,feeRateObject.onCellClick);
         feeRateObject.feeRateSheet.bind(GC.Spread.Sheets.Events.CellDoubleClick,feeRateObject.onCellDoubleClick);
     },
-    showSelectTree:function () {
-        var sheet= feeRateObject.feeRateSheet;
-        var setting=feeRateObject.sheetSetting;
-        var data = projectObj.project.FeeRate.getActivateFeeRate().rates;
+    showSelectTree:function (sheet,setting,data) {
         var ch = GC.Spread.Sheets.SheetArea.viewport;
         var groups=[];
         sheet.suspendPaint();
@@ -370,38 +380,100 @@ var feeRateObject={
         this.mainViews.invalidate();
         document.querySelector('#divFee').focus();
     },
+    initFeeRateSpread:function (rowCount) {
+        //初始化费用项表格
+        this.mainFeeRateSpread = sheetCommonObj.buildSheet($('#divFee')[0], this.mainFeeRateSetting,rowCount);
+        this.mainFeeRateSpread.options.scrollbarMaxAlign = true;
+        this.mainFeeRateSheet = this.mainFeeRateSpread.getSheet(0);
+        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.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){//有子节点时不能编辑费率列
+                args.cancel = true;
+            }
+        });
+        this.mainFeeRateSheet.name('mainFeeRateSheet');
+    },
+    showMainFeeRateData:function () {
+        let me = this;
+        me.activateFeeRate = projectObj.project.FeeRate.getActivateFeeRate();
+        me.mainFeeRateData = projectObj.project.FeeRate.getActivateFeeRate().rates;
+        me.mainFeeRateSheet.setRowCount(0);
+        me.mainFeeRateSheet.setRowCount(me.mainFeeRateData.length);
+        me.showSelectTree(me.mainFeeRateSheet,me.mainFeeRateSetting,me.mainFeeRateData);
+    },
     reFreshRateViews:function() {
-        feeRateObject.createSpreadView();
+        //feeRateObject.createSpreadView();
+        feeRateObject.loadPageContent();
+        this.showMainFeeRateData();
+        if(subRateObject.subRateSpread){//如果子费率没有初始化过的话,不需要显示。
+            subRateObject.initSubRateSpread(this.mainFeeRateData[0]);
+        }
+    },
+    onMainFeeRateSheetValueChange:function (e,info) {
+        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;
+        if(fieldID == 'rate'&&value != null){
+            if(number_util.isNumber(parseFloat(value))){
+                value = scMathUtil.roundForObj(value,getDecimal("feeRate"));
+            }else {
+                alert('当前输入的数据类型不正确,请重新输入。');
+                me.mainFeeRateSheet.setValue(info.row, info.col, info.oldValue);
+                return;
+            }
+        }
+        if(recode[fieldID] == value){//没有改变
+            return;
+        }
+        updateData[fieldID] = value;
+        $.bootstrapLoading.start();
+         feeRate.updateFeeRateByID(recode.ID,updateData,function () {
+            if(fieldID == 'rate'){
+                feeRate.onFeeRateChange(recode.ID,value);
+            }
+            $.bootstrapLoading.end();
+        })
+    },
+
+    onMainFeeRateSelectChanged:function (e, info) {
+        let me = feeRateObject;
+        let row = info.newSelections[0].row;
+        if(row!=-1){
+            subRateObject.initSubRateSpread(me.mainFeeRateData[row]);
+        }
     },
     updateBySelect:function (rate,selectMap,mapID) {
-       var selected = this.mainViews.getSelections()[0];
+        let selected = this.mainFeeRateSheet.getSelections()[0];
         projectObj.project.FeeRate.backupDatas();
-       var item = this.datas[selected.sourceRow];
+        let item = this.mainFeeRateData[selected.row];
         item.rate = rate;
-        _.forEach(selectMap,function (value,key) {
-            var recode =  item.subFeeRate.recodes[key];
-            var optionList = recode.optionList;
-            _.forEach(optionList,function (o) {
-                if(o.value==value){
+        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;
                 }
-            })
-        })
+            }
+        }
         if($('#cascadeSet').prop('checked')){
-            this.cascadeSetRates(item,selected.sourceRow,mapID,selectMap)
+            this.cascadeSetRates(item,selected.row,mapID,selectMap);
         }else {
-            this.mainViews.data.updateItem(selected.sourceRow,item);
+            projectObj.project.FeeRate.batchUpdateFeeRate([{rateIndex:selected.row,rate:item}],feeRateObject.activateFeeRate);
         }
-        //projectObj.project.FeeRate.synchronizeFeeRate();
-
-        //this.views.data.updateItem()
     },
     cascadeSetRates:function(selectedItem,sourceRow,mapID,selectMap){
         var items=[];
         items.push({rateIndex:sourceRow,rate:selectedItem});
-        _.forEach(this.datas,function (recode,Index) {
+        _.forEach(this.mainFeeRateData,function (recode,Index) {
             if(Index!=sourceRow&&recode.subFeeRate){
                 var valueMaps = recode.subFeeRate.valueMaps;
                 var valueMap = _.find(valueMaps,{ID:mapID});
@@ -415,7 +487,7 @@ var feeRateObject={
                             var optionList = tempRecode.optionList;
                             _.forEach(optionList,function (o) {
                                 if(o.value==value){
-                                    o.selected=true;
+                                    o.selected = true;
                                 }else {
                                     o.selected = false;
                                 }
@@ -493,10 +565,8 @@ var feeRateObject={
     changeFeeRateStandard:function(newVal){
         $.bootstrapLoading.start();
         var callback=function () {
-            feeRateObject.createSpreadView();
-            feeRateObject.loadPageContent();
-            projectObj.project.FeeRate.synchronizeFeeRate();
-            subRateObject.destorySpreadView();
+            feeRateObject.reFreshRateViews();
+            projectObj.project.FeeRate.onFeeRateFileChange();
             $.bootstrapLoading.end();
         };
         projectObj.project.FeeRate.changeFeeRateStandard(newVal,callback);
@@ -595,8 +665,8 @@ var feeRateObject={
             name:name
         }
         var callback=function () {
-            feeRateObject.createSpreadView();
-            feeRateObject.loadPageContent();
+            //feeRateObject.createSpreadView();
+            feeRateObject.reFreshRateViews();
             projectObj.project.FeeRate.onFeeRateFileChange();
             $.bootstrapLoading.end();
         }
@@ -621,8 +691,7 @@ var feeRateObject={
     changeFeeRateFileConfirm:function(feeRateFileID,name){
         $.bootstrapLoading.start();
         var callback=function () {
-            feeRateObject.createSpreadView();
-            feeRateObject.loadPageContent();
+            feeRateObject.reFreshRateViews();
             projectObj.project.FeeRate.onFeeRateFileChange();
             $.bootstrapLoading.end();
         }
@@ -670,11 +739,13 @@ var feeRateObject={
         var data={'projectID': projectObj.project.ID(),'templatesID': calInfo.template.ID,'calcItem': calInfo.calcItem};
         $.bootstrapLoading.start();
         calcProgramManage.saveCalcItem(data,function (result) {
+            $.bootstrapLoading.end();
             calInfo.calcItem.feeRate=rate.rate;
             projectObj.project.calcProgram.compileAllTemps();
             projectObj.project.calcProgram.calcAllNodesAndSave();
             calcProgramManage.refreshDetailSheet();
             $("#fee_rate_tree").modal('hide');
+            $.bootstrapLoading.end();
         });
         console.log(calInfo);
     },
@@ -715,9 +786,13 @@ $(function(){
     );
 
     $('#tab_fee_rate').on('shown.bs.tab', function (e) {
+        let me = feeRateObject;
         $(e.relatedTarget.hash).removeClass('active');
-        feeRateObject.reFreshRateViews();
-        feeRateObject.loadPageContent();
+        if(me.mainFeeRateSpread == null){
+            me.initFeeRateSpread(0);
+        }
+        me.showMainFeeRateData();
+        me.loadPageContent();
     });
 
     $('#setNewFeeRate').bind('click', function () {
@@ -844,7 +919,7 @@ $(function(){
             feeRateObject.createSheet();
         }
         feeRateObject.feeRateSelection=null;
-        feeRateObject.showSelectTree();
+        feeRateObject.showSelectTree(feeRateObject.feeRateSheet,feeRateObject.sheetSetting,projectObj.project.FeeRate.getActivateFeeRate().rates);
     });
 
     $('#fee_rate_tree').on('hidden.bs.modal', function (e) {

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

@@ -274,6 +274,14 @@ var gljOprObj = {
         sheet.bind(GC.Spread.Sheets.Events.CellClick, me.onCellClick);
         sheet.bind(GC.Spread.Sheets.Events.CellDoubleClick, me.onCellDoubleClick);
         sheet.bind(GC.Spread.Sheets.Events.ClipboardChanged, me.onClipboardChanged);
+        sheet.bind(GC.Spread.Sheets.Events.EditStarting, function (sender, args) {
+            if (args.row>=me.sheetData.length){
+                args.cancel = true;
+            }
+            if (me.sheetData[args.row].isMixRatio) {
+                args.cancel = true;
+            }
+        });
         gljContextMenu.loadGLJSpreadContextMenu();
     },
     initCoeSheet: function (sheet) {
@@ -745,8 +753,11 @@ var gljOprObj = {
         return rowstr;
 
     },
-    showDataIfRationSelect: function (node) {
+    showDataIfRationSelect: function (node,selectedNodeId) {
         var isShow = false;
+        if(selectedNodeId){
+            this.selectedNodeId = selectedNodeId;
+        }
         if (node) {
             if (this.selectedNodeId && this.selectedNodeId == node.getID()) {
                 return;

+ 33 - 7
web/building_saas/main/js/views/installation_fee_view.js

@@ -599,8 +599,13 @@ let installationFeeObj={
         me.rationInstallSheet.repaint();
     },
     onFeeRuleDoubleClick:function (e,info) {
+        let from = $("#more_from").val();
         if(info.row!=undefined||info!=null){
-            installationFeeObj.updateFeeRuleToSection(info.row);
+            if(from =='feeDetail'){
+                installationFeeObj.updateFeeRuleToSection(info.row);
+            }else if(from == 'rationInstallation'){//在定额安装增加费那里点击更多
+                installationFeeObj.updateFeeRuleToRInstall(info.row);
+            }
         }else {
             return;
         }
@@ -778,7 +783,10 @@ let installationFeeObj={
             }
             if(updateMap){//如果有需要更新的属性
                 if(modifyRule.base&&installSectionBase.indexOf(modifyRule.base)>0){
-                    let sum = modifyRule.labour+modifyRule.material+modifyRule.machine;//三项的和要等于100
+                    let temLabour = modifyRule.labour?modifyRule.labour:0;
+                    let temMaterial = modifyRule.material?modifyRule.material:0;
+                    let temMachine = modifyRule.machine?modifyRule.machine:0;
+                    let sum = temLabour+temMaterial+temMachine;//三项的和要等于100
                     if(sum!=100){
                        alert("人工、材料、机械的和应等于100,请重新输入。");
                        return;
@@ -787,7 +795,14 @@ let installationFeeObj={
                 $("#modify_feeRule").modal('hide');
                 installation_fee.updateFeeRule(updateMap,modifyRule.libID,modifyRule.ID,function () {
                     me.refreshRationInstallationRow(me.rationInstallSheet.getSelections()[0].row);
+                    installation_fee.calcInstallationFee(function (isChange) {
+                        if(isChange){
+                            projectObj.project.calcProgram.calcAllNodesAndSave();
+                        }
+                    });
                 });
+            }else {
+                $("#modify_feeRule").modal('hide');
             }
         }
     },
@@ -937,10 +952,19 @@ let installationFeeObj={
         let me = installationFeeObj;
         let feeItem = this.feeItemData[info.row];
         let header = this.feeItemSetting.header[info.col];
-        let doc={};
+        let doc={},cleanPosition = false;
         doc[header.dataCode] = info.newValue;
-        projectObj.project.installation_fee.updateFeeItem(doc,feeItem.libID,feeItem.ID,function () {
+        if(header.dataCode=='feeType'&&info.newValue == '子目费用'){
+            doc.position = '';
+            doc.billID = '';
+            cleanPosition = true;
+        }
+        projectObj.project.installation_fee.updateFeeItem(doc,feeItem.libID,feeItem.ID,cleanPosition,function () {
             me.feeItemSheet.getCell(info.row, info.col).value(info.newValue);
+            if(cleanPosition==true){
+                me.feeItemSheet.getCell(info.row, info.col+1).value("");
+                me.showFeeDetailData(feeItem.libID,feeItem.ID);
+            }
         });
     },
     onRationInstallValueChange:function (e,info) {
@@ -1114,7 +1138,10 @@ let installationFeeObj={
         if(this.feeDetailData&&this.feeDetailData.length>0&&this.feeDetailData[os.row]){
             let detail = this.feeDetailData[os.row];
             if(detail.base&&installSectionBase.indexOf(detail.base)>0){
-                let sum = detail.labour+detail.material+detail.machine;//三项的和要等于100
+                let temLabour = detail.labour?detail.labour:0;
+                let temMaterial = detail.material?detail.material:0;
+                let temMachine = detail.machine?detail.machine:0;
+                let sum = temLabour+temMaterial+temMachine;//三项的和要等于100
                 if(sum!=100){
                     setTimeout(function () {//这里须用延时执行的办法,不然的弹窗确认窗口会和spreadjs 的事件有冲突
                         alert("人工、材料、机械的和应等于100,请重新输入。");
@@ -1218,9 +1245,8 @@ let installationFeeObj={
         install_fee.calcInstallationFee(function (isChange) {
             if(isChange){
                 projectObj.project.calcProgram.calcAllNodesAndSave();
-                installationFeeObj.showRationInstallationData(projectObj.project.mainTree.selected);
             }
-            console.log("cal end");
+            installationFeeObj.showRationInstallationData(projectObj.project.mainTree.selected);
         });
     },
     initSettingRadio:function () {

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

@@ -599,7 +599,9 @@ var projectObj = {
                 that.project.projectMarkChecking();//是否需要重新进行造价计算
                 installationFeeObj.engineeringTypeChecking();//检查是否安装工程
                 //初始需要触发一次点击表格事件,sheet.getAutoFitWidth值(获取单元格文本长度)才正确
-
+                //autoFlashHeight();//设置界面高度
+               // that.mainSpread.refresh();
+                $(window).resize();
             }
             else {
 

+ 74 - 1
web/building_saas/main/js/views/sub_fee_rate_views.js

@@ -7,6 +7,23 @@ var subRateObject={
     datas:null,
     valueMap:null,
     canEdit:true,
+    subRateSpread:null,
+    subRateSheet:null,
+    subRateSetting:{
+        header: [
+            {headerName: "参数名称", headerWidth: 250, dataCode: "name", dataType: "String"},
+            {headerName: "参数值", headerWidth: 200, dataCode: "optionValue", dataType: "String",getText:'forOption'}
+        ],
+        view: {
+            lockColumns: [0]
+        },
+        getText:{
+            forOption:function (item,val) {
+                let o = _.find(item.optionList,{'selected':true});
+                return o?o.value:'';
+            }
+        }
+    },
     columns: [
         {
             id: 'name',
@@ -59,11 +76,48 @@ var subRateObject={
         this.addComboboxOption(this.datas);
 
     },
-       reFreshRateViews:function(sender,args) {
+    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]);
+            this.subRateSheet = this.subRateSpread.getSheet(0);
+            sheetCommonObj.initSheet(this.subRateSheet, this.subRateSetting, 30);
+            this.subRateSheet.bind(GC.Spread.Sheets.Events.SelectionChanged, this.onSubRateSelectChanged);
+            this.subRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onSubRateValueChange);
+            //this.subRateSheet.bind(GC.Spread.Sheets.Events.ValueChanged, me.onSheetValueChange);
+            this.subRateSheet.name('subRateSheet');
+        }
+        subRateObject.datas = projectObj.project.FeeRate.getSubViewData(item);
+        subRateObject.valueMap=projectObj.project.FeeRate.getValueMap(item);
+        console.log(subRateObject.datas);
+        console.log(subRateObject.valueMap);
+        subRateObject.showSubRateData();
+    },
+    showSubRateData:function () {
+        this.subRateSheet.setRowCount(0);
+        sheetCommonObj.showData(this.subRateSheet, this.subRateSetting, this.datas);
+        this.subRateSheet.setRowCount(this.datas.length);
+        for(let row =0; row < this.datas.length;row++){
+            this.setComboOptionCell(row,1,this.datas[row],this.subRateSheet);
+        }
+    },
+    onSubRateSelectChanged:function (e,info) {
+        info.sheet.repaint();
+    },
+    setComboOptionCell:function(row,col,subRate,sheet){
+        let options=[];
+        for(let op of subRate.optionList){
+            options.push({text:op.name,value:op.value});
+        }
+        let dynamicCombo = sheetCommonObj.getDynamicCombo();//new GC.Spread.Sheets.CellTypes.ComboBox();
+        dynamicCombo.items(options);
+        dynamicCombo.editorValueType(GC.Spread.Sheets.CellTypes.EditorValueType.value);
+        sheet.setCellType(row, col, dynamicCombo, GC.Spread.Sheets.SheetArea.viewport);
+    },
     addComboboxOption:function (datas) {
         //<option value ="volvo">Volvo</option> <option value ="saab">Saab</option> <option value="opel">Opel</option> <option value="audi">Audi</option>
         _.forEach(datas,function (item) {
@@ -94,6 +148,25 @@ var subRateObject={
             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;
+                }
+                selectValueList.push(selectMap[key]);
+            })
+            var mapID =selectValueList.join('-');
+            var rate = me.valueMap[mapID];
+            feeRateObject.updateBySelect(rate,selectMap,mapID);
+        }
+    },
+
     destorySpreadView:function () {
         if(this.views){
             this.views.destroy();

+ 4 - 17
web/building_saas/pm/html/project-management-Recycle.html

@@ -2,25 +2,12 @@
     <legend class="m-0 pb-1">全部</legend>
 </div>
 <div class="top-content">
-    <div class="main-data-top" id="gc_waiting">
+  <!--  <div class="main-data-top" id="gc_waiting">
         <p style="text-align: center; margin-top: 30px;">正在加载数据...</p>
-    </div>
+    </div>-->
 </div>
-<div class="poj-list">
-    <table class="table table-hover table-sm mb-5" id="gcTree">
-        <thead>
-        <tr>
-            <th width="50%">工程列表</th>
-            <th width="10%">删除日期</th>
-            <th width="10%">创建日期</th>
-            <th width="10%">恢复</th>
-            <th width="10%">单价文件</th>
-            <th width="10%">费率文件</th>
-        </tr>
-        </thead>
-        <tbody>
-        </tbody>
-    </table>
+<div class="poj-list" id="gcSpread">
+
 </div>
 <!--弹出恢复项目-->
 <div class="modal fade" id="rePoj" data-backdrop="static">

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

@@ -63,7 +63,7 @@
                     </div>
                     <ul class="nav nav-pills flex-column">
                         <li class="nav-item">
-                            <a class="nav-link active" href="#pm_all" role="tab" id="tab_pm_all" data-toggle="tooltip" data-placement="right" data-original-title="全部"><i class="fa fa-bars"></i></a>
+                            <a class="nav-link active" href="#pm_all" role="tab" id="tab_pm_all" data-toggle="tab" data-placement="right" data-original-title="全部"><i class="fa fa-bars"></i></a>
                         </li>
                         <li class="nav-item">
                             <a class="nav-link" href="#"  data-toggle="tooltip" data-placement="right" data-original-title="最近使用"><i class="fa fa-bookmark"></i></a>
@@ -78,14 +78,14 @@
                             <a class="nav-link" href="#"  data-toggle="tooltip" data-placement="right" data-original-title="归档"><i class="fa fa-book"></i></a>
                         </li>
                         <li class="nav-item">
-                            <a class="nav-link" href="#pm_gc" id="tab_pm_gc" data-toggle="tooltip" data-placement="right" data-original-title="回收站"><i class="fa fa-trash"></i></a>
+                            <a class="nav-link" href="#pm_gc" id="tab_pm_gc" data-toggle="tab" data-placement="right" data-original-title="回收站"><i class="fa fa-trash"></i></a>
                         </li>
                     </ul>
                 </div>
             </div>
             <div class="pm-content">
                 <div class="tab-content">
-                    <div class="tab-pane active">
+                    <div class="tab-pane active" id="pm_all" role="tabpanel">
                         <div class="toolsbar">
                             <div class="tools-btn btn-group align-top">
                                 <a href="javascript:void(0);"  id="add-tender-btn" class="btn btn-sm"><i class="fa fa-sticky-note-o"></i>新建单位工程</a>
@@ -108,9 +108,9 @@
                         </div>
                         <div class="poj-list" id="projSpread">
                         </div>
-                        <div class="tab-pane" role="tabpanel" id="pm_gc">
-                            <%include project-management-Recycle.html %>
-                        </div>
+                    </div>
+                    <div class="tab-pane" role="tabpanel" id="pm_gc">
+                        <%include project-management-Recycle.html %>
                     </div>
                 </div>
             </div>

+ 456 - 14
web/building_saas/pm/js/pm_gc.js

@@ -159,29 +159,471 @@ let gcTreeSetting = {
         }
     ]
 };
+const gcTreeObj = {
+    tree: null,
+    workBook: null,
+    setting: {
+        tree: {
+            id: 'ID',
+            pid: 'ParentID',
+            nid: 'NextSiblingID',
+            rootId: -1,
+            autoUpdate: false
+        },
+        header: [
+            {name: '工程列表', dataCode: 'name', width: 800, vAlign: 'center', hAlign: 'left'},
+            {name: '删除日期', dataCode: 'deleteDateTime', width: 170, vAlign: 'center', hAlign: 'left'},
+            {name: '创建日期', dataCode: 'createDateTime', width: 170, vAlign: 'center', hAlign: 'left'},
+            {name: '恢复', dataCode: 'recovery', width: 170, vAlign: 'center', hAlign: 'left'},
+            {name: '单价文件', dataCode: 'unitPriceFile', width: 170, vAlign: 'center', hAlign: 'left'},
+            {name: '费率文件', dataCode: 'feeRateFile', width: 170, vAlign: 'center', hAlign: 'left'}
+        ],
+        options: {
+            tabStripVisible:  false,
+            allowCopyPasteExcelStyle : false,
+            allowExtendPasteRange: false,
+            allowUserDragDrop : false,
+            allowUserDragFill: false,
+            scrollbarMaxAlign : true
+        }
+    },
+    renderSheetFuc: function (sheet, fuc) {
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        fuc();
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+    setOptions: function (workbook, opts) {
+        for(let opt in opts){
+            workbook.options[opt] = opts[opt];
+        }
+    },
+    bindEvent: function (workBook) {
+        const _events = GC.Spread.Sheets.Events;
+        let sheet = workBook.getActiveSheet();
+        //改变选中节点set selected
+        sheet.bind(_events.SelectionChanging, this.onSelectionChanging);
+    },
+    buildHeader: function (sheet, headers) {
+        let me = this;
+        let fuc = function () {
+            sheet.options.isProtected = true;
+            sheet.options.protectionOptions = {
+                allowResizeRows: true,
+                allowResizeColumns: true
+            };
+            sheet.setColumnCount(headers.length);
+            sheet.setRowHeight(0, 40, GC.Spread.Sheets.SheetArea.colHeader);
+            for(let i = 0, len = headers.length; i < len; i++){
+                sheet.setValue(0, i, headers[i].name, GC.Spread.Sheets.SheetArea.colHeader);
+                sheet.setColumnWidth(i, headers[i].width, GC.Spread.Sheets.SheetArea.colHeader);
+            }
+        };
+        me.renderSheetFuc(sheet, fuc);
+    },
+    buildSheet: function () {
+        if(!this.workBook){
+            this.workBook = new GC.Spread.Sheets.Workbook($('#gcSpread')[0], {sheetCount: 1});
+            this.setOptions(this.workBook, this.setting.options);
+            this.buildHeader(this.workBook.getActiveSheet(), this.setting.header);
+            this.bindEvent(this.workBook);
+        }
+    },
+    initSelection: function (row) {
+        let me = this;
+        let node = me.tree.items[row];
+        me.tree.selected = node;
+        $(".tools-btn > a").not(".disabled").addClass("disabled");
+        $("#add-engineering-btn").addClass("disabled");
+        $('#add-tender-btn').removeClass('disabled');
+        if(node){
+            switch(node.data.projType) {
+                case projectType.project:
+                    $("#del-btn").removeClass("disabled");
+                    $("#add-engineering-btn").removeClass("disabled");
+                    break;
+                case projectType.folder:
+                    if(!node.children || node.children.length === 0){
+                        $("#del-btn").removeClass("disabled");
+                    }
+                    break;
+                case projectType.engineering:
+                    $("#del-btn").removeClass("disabled");
+                    $("#add-engineering-btn").removeClass("disabled");
+                    break;
+                case projectType.tender:
+                    $("#add-engineering-btn").removeClass("disabled");
+                    $("#move-to-btn").removeClass("disabled");
+                    $("#copy-to-btn").removeClass("disabled");
+                    $("#share-btn").removeClass("disabled");
+                    $("#cooperate-btn").removeClass("disabled");
+                    $("#del-btn").removeClass("disabled");
+                    break;
+            }
+            $("#rename-btn").removeClass("disabled");
+        }
+    },
+    onSelectionChanging: function (sender, args) {
+        let me = gcTreeObj;
+        me.initSelection(args.newSelections[0].row);
+    },
+    //点击恢复列,弹出恢复项目窗口
+    recoveryProj: function (node) {
+        let tenderNodes = m_getTenders(node);
+        $('#rePoj .modal-header').empty();
+        $('p', '#rePoj .modal-body').remove();
+        $('#rePoj .modal-header').html(v_getTitle(node));
+        $('#rePoj .modal-body').html(v_getMoBody(node, tenderNodes));
+        $('#rePoj').modal('show');
+    },
+    //点击单价文件恢复,弹出恢复单价文件窗口
+    recoveryUnitPrc: function (node) {
+        let unitPriceFiles = node.data.unitPriceFiles;
+        $('#reFile h5').text('恢复单价文件');
+        $('tr', '#reFile tbody').remove();
+        $('#reFile tbody').html(v_getFiles(fileType.unitPriceFile, unitPriceFiles));
+        $('#reFile').modal('show');
+    },
+    recoveryFeeRate: function (node) {
+        let feeRateFiles = node.data.feeRateFiles;
+        $('#reFile h5').text('恢复费率文件');
+        $('tr', '#reFile tbody').remove();
+        $('#reFile tbody').html(v_getFiles(fileType.feeRateFile, feeRateFiles));
+        $('#reFile').modal('show');
+    },
+    getTreeNodeCell: function (tree) {
+        let indent = 20;
+        let levelIndent = -5;
+        let halfBoxLength = 5;
+        let halfExpandLength = 3;
+        let imgWidth = 18;
+        let imgHeight = 14;
+        let TreeNodeCellType = function () {
+        };
+        TreeNodeCellType.prototype = new GC.Spread.Sheets.CellTypes.Text();
+        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            if (style.backColor) {
+                ctx.save();
+                ctx.fillStyle = style.backColor;
+                ctx.fillRect(x, y, w, h);
+                ctx.restore();
+            } else {
+                ctx.clearRect(x, y, w, h);
+            }
+            let drawLine = function (canvas, x1, y1, x2, y2, color) {
+                ctx.save();
+                ctx.translate(0.5, 0.5);
+                ctx.beginPath();
+                ctx.moveTo(x1, y1);
+                ctx.lineTo(x2, y2);
+                ctx.strokeStyle = color;
+                ctx.stroke();
+                ctx.restore();
+            };
+            let drawExpandBox = function (ctx, x, y, w, h, centerX, centerY, expanded) {
+                let rect = {}, h1, h2, offset = 1;
+                rect.top = centerY - halfBoxLength;
+                rect.bottom = centerY + halfBoxLength;
+                rect.left = centerX - halfBoxLength;
+                rect.right = centerX + halfBoxLength;
 
+                if (rect.left < x + w) {
+                    rect.right = Math.min(rect.right, x + w);
+
+                    ctx.save();
+                    ctx.translate(0.5, 0.5);
+                    ctx.strokeStyle = 'black';
+                    ctx.beginPath();
+                    ctx.moveTo(rect.left, rect.top);
+                    ctx.lineTo(rect.left, rect.bottom);
+                    ctx.lineTo(rect.right, rect.bottom);
+                    ctx.lineTo(rect.right, rect.top);
+                    ctx.lineTo(rect.left, rect.top);
+                    ctx.stroke();
+                    ctx.fillStyle = 'white';
+                    ctx.fill();
+                    ctx.restore();
+
+                    // Draw Horizontal Line
+                    h1 = centerX - halfExpandLength;
+                    h2 = Math.min(centerX + halfExpandLength, x + w);
+                    if (h2 > h1) {
+                        drawLine(ctx, h1, centerY, h2, centerY, 'black');
+                    }
+                    // Draw Vertical Line
+                    if (!expanded && (centerX < x + w)) {
+                        drawLine(ctx, centerX, centerY - halfExpandLength, centerX, centerY + halfExpandLength, 'black');
+                    }
+                }
+
+            }
+            let node = tree.items[options.row];
+            let showTreeLine = true;
+            if (!node) { return; }
+
+            let centerX = Math.floor(x) + node.depth() * indent + node.depth() * levelIndent + indent / 2;
+            let x1 = centerX + indent / 2;
+            let centerY = Math.floor((y + (y + h)) / 2);
+            let y1;
+            // Draw Sibling Line
+            if (showTreeLine) {
+                // Draw Horizontal Line
+                if (centerX < x + w) {
+                    drawLine(ctx, centerX, centerY, Math.min(x1, x + w), centerY, 'gray');
+                    let img;
+                    if(node.data.projType === projectType.folder){
+                        img = document.getElementById('folder_open_pic');
+                        imgWidth = 15;
+                    }
+                    else if(node.data.projType === projectType.project){
+                        img = document.getElementById('proj_pic');
+                        imgWidth = 18;
+                    }
+                    else if(node.data.projType === projectType.engineering){
+                        img = document.getElementById('eng_pic');
+                        imgWidth = 14;
+                    }
+                    else if(node.data.projType === projectType.tender){
+                        img = document.getElementById('tender_pic');
+                        imgWidth = 14;
+                    }
+                    ctx.drawImage(img, centerX+indent/2+3, centerY - 7, imgWidth,imgHeight);
+                }
+                // Draw Vertical Line
+                if (centerX < x + w) {
+                    y1 = node.isLast() ? centerY : y + h;
+                    if (node.isFirst() && !node.parent.parent) {
+                        drawLine(ctx, centerX, centerY, centerX, y1, 'gray');
+                    } else {
+                        drawLine(ctx, centerX, y, centerX, y1, 'gray');
+                    }
+                }
+            }
+            // Draw Expand Box
+            if (node.children.length > 0) {
+                drawExpandBox(ctx, x, y, w, h, centerX, centerY, node.expanded);
+            }
+            // Draw Parent Line
+            if (showTreeLine) {
+                var parent = node.parent, parentCenterX = centerX - indent - levelIndent;
+                while (parent.parent) {
+                    if (!parent.isLast()) {
+                        if (parentCenterX < x + w) {
+                            drawLine(ctx, parentCenterX, y, parentCenterX, y + h, 'gray');
+                        }
+                    }
+                    parent = parent.parent;
+                    parentCenterX -= (indent + levelIndent);
+                }
+            };
+            // Draw Text
+            //x = x + (node.depth() + 1) * indent +  node.depth() * levelIndent;
+            x = x + (node.depth() + 1) * indent +  node.depth() * levelIndent + imgWidth + 3;
+            GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
+        };
+        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea,
+                isReservedLocation: true
+            };
+        };
+        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
+            let offset = -1;
+            let node = tree.items[hitinfo.row];
+            tree.selected = node;
+            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 (!node || node.children.length === 0) { return; }
+
+            if (hitinfo.x > centerX - halfBoxLength && hitinfo.x < centerX + halfBoxLength && hitinfo.y > centerY - halfBoxLength && hitinfo.y < centerY + halfBoxLength) {
+                node.setExpanded(!node.expanded);
+                TREE_SHEET_HELPER.massOperationSheet(hitinfo.sheet, function () {
+                    let iCount = node.posterityCount(), i, child;
+                    for (i = 0; i < iCount; i++) {
+                        child = tree.items[hitinfo.row + i + 1];
+                        hitinfo.sheet.setRowVisible(hitinfo.row + i + 1, child.visible, hitinfo.sheetArea);
+                    }
+                    hitinfo.sheet.invalidateLayout();
+                });
+                hitinfo.sheet.repaint();
+            }
+        };
+        return new TreeNodeCellType();
+    },
+    getBaseCell: function () {
+        let MyBaseCell = function () {
+        };
+        MyBaseCell.prototype = new GC.Spread.Sheets.CellTypes.Text();
+        MyBaseCell.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea,
+                isReservedLocation: true
+            };
+        };
+        MyBaseCell.prototype.processMouseDown = function (hitinfo) {
+            let dataCode = gcTreeObj.setting.header[hitinfo.col]['dataCode'];
+            let node = gcTreeObj.tree.items[hitinfo.row];
+            let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
+            let value = hitinfo.sheet.getValue(hitinfo.row, hitinfo.col);
+            let acStyle = hitinfo.sheet.getActualStyle(hitinfo.row, hitinfo.col),
+                zoom = hitinfo.sheet.zoom();
+            let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitinfo.sheet, row: hitinfo.row, col: hitinfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
+            if(hitinfo.x - hitinfo.cellRect.x > 0 && hitinfo.x - hitinfo.cellRect.x < textLength){
+                if(dataCode === 'recovery'){
+                    gcTreeObj.recoveryProj(node);
+                }
+                else if(dataCode === 'unitPriceFile'){
+                    gcTreeObj.recoveryUnitPrc(node);
+                }
+                else if(dataCode === 'feeRateFile'){
+                    gcTreeObj.recoveryFeeRate(node);
+                }
+            }
+        };
+        MyBaseCell.prototype.processMouseMove = function (hitInfo) {
+            let dataCode = gcTreeObj.setting.header[hitInfo.col]['dataCode'];
+            if(dataCode === 'recovery' || dataCode === 'unitPriceFile' || dataCode === 'feeRateFile'){
+                let sheet = hitInfo.sheet;
+                let div = sheet.getParent().getHost();
+                let canvasId = div.id + "vp_vp";
+                let canvas = $(`#${canvasId}`)[0];
+                //改变鼠标图案
+                let text = hitInfo.sheet.getText(hitInfo.row, hitInfo.col);
+                let value = hitInfo.sheet.getValue(hitInfo.row, hitInfo.col);
+                let acStyle = hitInfo.sheet.getActualStyle(hitInfo.row, hitInfo.col),
+                    zoom = hitInfo.sheet.zoom();
+                let textLength = this.getAutoFitWidth(value, text, acStyle, zoom, {sheet: hitInfo.sheet, row: hitInfo.row, col: hitInfo.col, sheetArea: GC.Spread.Sheets.SheetArea.viewport});
+                if (sheet && hitInfo.x - hitInfo.cellRect.x >  0 && hitInfo.x - hitInfo.cellRect.x < textLength) {
+                    canvas.style.cursor='pointer';
+                    return true;
+                }else{
+                    canvas.style.cursor='default';
+                }
+            }
+            return false;
+        };
+        return new MyBaseCell();
+    },
+    setCellValue: function (cell, node) {
+        const sheet = this.workBook.getActiveSheet();
+        const {row, col} = cell;
+        const dataCode = this.setting.header[col]['dataCode'];
+        let value = '';
+        if(dataCode === 'deleteDateTime' || dataCode === 'createDateTime'){
+            if (node.data.projType === projectType.tender && deleted(node)) {
+                let date = dataCode === 'deleteDateTime' ? node.data.deleteInfo.deleteDateTime : node.data.createDateTime;
+                let localDateTime = new Date(date).toLocaleDateString();
+                value = new Date(localDateTime).Format('yyyy-MM-dd');
+            }
+        }
+        else if(dataCode === 'recovery'){
+            if(deleted(node)){
+                value = '恢复';
+            }
+        }
+        else if(dataCode === 'unitPriceFile'){
+            if(node.data.projType === projectType.project && node.data.unitPriceFiles !== undefined && node.data.unitPriceFiles.length > 0){
+                value = '恢复';
+            }
+        }
+        else if(dataCode === 'feeRateFile'){
+            if(node.data.projType === projectType.project && node.data.feeRateFiles !== undefined && node.data.feeRateFiles.length > 0){
+                value = '恢复';
+            }
+        }
+        else {
+            value = node.data[dataCode] ? node.data[dataCode] : '';
+        }
+        sheet.setValue(row, col, value);
+    },
+    showTreeData: function (nodes, headers) {
+        let me = this;
+        let sheet = me.workBook.getActiveSheet();
+        let fuc = function(){
+            sheet.setRowCount(nodes.length);
+            for(let i = 0; i < nodes.length; i++){
+                let treeNodeCell = me.getTreeNodeCell(me.tree);
+                sheet.getCell(i, 0).cellType(treeNodeCell);
+                for(let j = 0; j < headers.length; j++){
+                    sheet.getRange(-1, j, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[j]['hAlign']]);
+                    sheet.getRange(-1, j, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[j]['vAlign']]);
+                    if(j !== 0){
+                        sheet.getCell(i, j).cellType(me.getBaseCell());
+                    }
+                    let dataCode = headers[j].dataCode;
+                    me.setCellValue({row: i, col: j}, nodes[i]);
+                }
+            }
+        };
+        me.renderSheetFuc(sheet, fuc);
+    },
+    refreshNodeData: function (node) {
+        let me = this;
+        let sheet = me.workBook.getActiveSheet();
+        let header = me.setting.header;
+        let rIdx = me.tree.items.indexOf(node);
+        me.renderSheetFuc(sheet, function () {
+            for(let i = 0; i < header.length; i++){
+                me.setCellValue({row: rIdx, col: i}, node);
+            }
+        });
+    },
+    remove: function (node) {
+        let me = this;
+        let sheet = me.workBook.getActiveSheet();
+        //删除行号
+        let rIdx = me.tree.items.indexOf(node);
+        //删除行数
+        let count = node.posterityCount() + 1;
+        me.tree.removeNode(node);
+        me.renderSheetFuc(sheet, function () {
+            sheet.deleteRows(rIdx, count);
+            sheet.setRowCount(me.tree.items.length);
+            me.initSelection(sheet.getActiveRowIndex());
+        });
+    },
+    move: function (orgRow, newRow) {
+        this.workBook.getActiveSheet().deleteRows(orgRow, 1);
+        this.addRow(this.tree.items[newRow]);
+    }
+};
 $(document).ready(function () {
     $('#tab_pm_gc').on('show.bs.tab', function () {
         //侧滑隐藏
         $('.slide-sidebar').removeClass('open');
         $('.slide-sidebar').css('width', '0');
-        $('#gc_waiting').show();
         gc_init();
-        Tree = null;
+        projTreeObj.tree = null;
     });
     e_recFiles($('#reFileBtn'));
     e_recProj($('#rePojBtn'));
 });
 
 function gc_init(){
-    let table = $('#gcTree');
-    $('thead', table).remove();
-    $('tbody', table).remove();
+    $.bootstrapLoading.start();
     a_getGC(function (datas) {
         m_buildVirtualTree(datas);
         let normalDatas = m_VTreeToDatas(datas);
-        gcTree = $.fn.treeTable.init(table, gcTreeSetting, normalDatas);
-        $('#gc_waiting').hide();
+        gcTreeObj.tree = pmTree.createNew(gcTreeObj.setting, normalDatas);
+        gcTreeObj.tree.selected = gcTreeObj.tree.items[0];
+        gcTreeObj.buildSheet();
+        gcTreeObj.showTreeData(gcTreeObj.tree.items, gcTreeObj.setting.header);
+        //初始选择
+        gcTreeObj.initSelection(0);
+        $.bootstrapLoading.end();
     });
 }
 
@@ -277,7 +719,7 @@ function v_recFiles(project, fileIds, type){
 }
 
 function v_removeNode(node){
-    gcTree.removeNode(node);
+    gcTreeObj.remove(node);
     let parent = node.parent || null;
     if(parent && parent.children.length === 0 && parent.data !== undefined){
         if(parent.data.projType === projectType.project && fileEmpty(parent)){
@@ -293,7 +735,7 @@ function v_refreshNode(node){
     if(deleted(node)){
         delete node.data.deleteInfo;
     }
-    gcTree.refreshNodesDom([node]);
+    gcTreeObj.refreshNodeData(node);
     let parent = node.parent || null;
     if(parent && parent.data !== undefined){
         v_refreshNode(parent);
@@ -495,7 +937,7 @@ function e_recFiles(btn){
             recIds.push(i.id);
         }
         let type = $('[name = "fileItems"]:checked').attr('fileType');
-        let selected = gcTree.selected();
+        let selected = gcTreeObj.tree.selected;
         //backend
         let updateDatas = [];
         for(let i = 0, len = recObjs.length; i < len; i++){
@@ -516,20 +958,20 @@ function e_recFiles(btn){
                     delete selected.data.deleteInfo;
                 }
                 if(fileEmpty(selected) && selected.children.length === 0){
-                    gcTree.removeNode(selected);
+                    gcTreeObj.remove(selected);
                 }
                 else {
-                    gcTree.refreshNodesDom([selected]);
+                    gcTreeObj.refreshNodeData(selected);
                 }
             }
         }
     });
 }
 
-//点击项目下的恢复操作(确认
+//点击项目下的恢复操作(确认
 function e_recProj(btn){
     btn.bind('click', function () {
-        let selected = gcTree.selected();
+        let selected = gcTreeObj.tree.selected;
         //backend
         let updateObj = m_getRecDatas(selected);
         let updateDatas = updateObj.proj.concat(updateObj.file);

+ 144 - 68
web/building_saas/pm/js/pm_newMain.js

@@ -377,6 +377,34 @@ const projTreeObj = {
         };
         return new TreeNodeCellType();
     },
+    setCellValue: function (cell, node) {
+        const sheet = this.workBook.getActiveSheet();
+        const {row, col} = cell;
+        let dataCode = this.setting.header[col]['dataCode'];
+        let value = '';
+        if(dataCode === 'engineeringCost'){
+            if(node.data.projType === projectType.tender){
+                value =  node.data.engineeringCost ? node.data.engineeringCost : 0;
+            }
+        }
+        else if(dataCode === 'unitPriceFile'){
+            if(node.data.projType === projectType.tender){
+                value = node.data.property && node.data.property.unitPriceFile && node.data.property.unitPriceFile.name ? node.data.property.unitPriceFile.name : '';
+            }
+        }
+        else if(dataCode === 'feeRateFile'){
+            if(node.data.projType === projectType.tender){
+                value = node.data.property && node.data.property.feeFile && node.data.property.feeFile.name ? node.data.property.feeFile.name : '';
+            }
+        }
+        else if(dataCode === 'createDateTime'){
+            value = node.data.createDateTime ? new Date(node.data.createDateTime).Format('yyyy-MM-dd') : '';
+        }
+        else {
+            value = node.data[dataCode] ? node.data[dataCode] : '';
+        }
+        sheet.setValue(row, col, value);
+    },
     showTreeData: function (nodes, headers) {
         let me = this;
         let sheet = me.workBook.getActiveSheet();
@@ -388,49 +416,22 @@ const projTreeObj = {
                 for(let j = 0; j < headers.length; j++){
                     sheet.getRange(-1, j, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[headers[j]['hAlign']]);
                     sheet.getRange(-1, j, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[headers[j]['vAlign']]);
+                    me.setCellValue({row: i, col: j}, nodes[i]);
                     let dataCode = headers[j].dataCode;
-                    sheet.setValue(i, j, nodes[i]['data'][dataCode]);
+                    //sheet.setValue(i, j, nodes[i]['data'][dataCode]);
                 }
             }
         };
         me.renderSheetFuc(sheet, fuc);
     },
-    addRow: function (node) {
-        const sheet = this.workBook.getActiveSheet();
-        const items = this.tree.items;
-        const rIdx = items.indexOf(node);
-        const cIdx = sheet.getActiveColumnIndex();
-        sheet.addRows(rIdx, 1);
-        //set selection selected
-        sheet.setSelection(rIdx, cIdx, 1, 1);
-        this.tree.selected = node;
-        //父节点收起时添加子节点,子节点添加完后隐藏
-        if(node.parent && !node.parent.expanded){
-            sheet.setRowVisible(rIdx, false);
-        }
-        sheet.getCell(rIdx, 0).cellType(this.getTreeNodeCell(this.tree));
-        this.refreshNodeData(sheet, node);
-    },
-    refreshNodeData: function (sheet, node) {
+    refreshNodeData: function (node) {
         let me = this;
-        //解决字段名不同
-        if(node.data.projType !== projectType.tender){
-            node.data.engineeringCost = '';
-            node.data.unitPriceFile = '';
-            node.data.feeRateFile = '';
-            node.data.createDateTime = '';
-        }
-        else{
-            node.data.engineeringCost = node.data.engineeringCost ? node.data.engineeringCost : 0;
-            node.data.unitPriceFile = node.data.property && node.data.property.unitPriceFile && node.data.property.unitPriceFile.name ? node.data.property.unitPriceFile.name : '';
-            node.data.feeRateFile = node.data.property && node.data.property.feeFile && node.data.property.feeFile.name ? node.data.property.feeFile.name : '';
-            node.data.createDateTime = node.data.createDateTime ? new Date(node.data.createDateTime).Format('yyyy-MM-dd') : '';
-        }
-        this.renderSheetFuc(sheet, function () {
-            let rIdx = me.tree.items.indexOf(node);
-            for(let col = 0; col < me.setting.header.length; col++){
-                let dataCode = me.setting.header[col]['dataCode'];
-                sheet.setValue(rIdx, col, node.data[dataCode]);
+        let sheet = me.workBook.getActiveSheet();
+        let header = me.setting.header;
+        let rIdx = me.tree.items.indexOf(node);
+        me.renderSheetFuc(sheet, function () {
+            for(let i = 0; i < header.length; i++){
+                me.setCellValue({row: rIdx, col: i}, node);
             }
         });
     },
@@ -439,21 +440,43 @@ const projTreeObj = {
         this.addRow(node);
         return node;
     },
-    remove: function (sheet) {
+    addRow: function (node) {
+        const me = this;
+        const sheet = this.workBook.getActiveSheet();
+        me.renderSheetFuc(sheet, function () {
+            const items = me.tree.items;
+            const rIdx = items.indexOf(node);
+            const cIdx = sheet.getActiveColumnIndex();
+            sheet.addRows(rIdx, 1);
+            //set selection selected
+            sheet.setSelection(rIdx, cIdx, 1, 1);
+            me.tree.selected = node;
+            //父节点收起时添加子节点,子节点添加完后隐藏
+            if(node.parent && !node.parent.expanded){
+                sheet.setRowVisible(rIdx, false);
+            }
+            sheet.getCell(rIdx, 0).cellType(me.getTreeNodeCell(me.tree));
+            me.refreshNodeData(node);
+        });
+    },
+    remove: function (sheet, rIdx, count) {
         let me = this;
         me.renderSheetFuc(sheet, function () {
-            let rIdx = me.tree.items.indexOf(me.tree.selected);
-            sheet.deleteRows(rIdx - 1, me.tree.selected.posterityCount());
+            sheet.deleteRows(rIdx, count);
             sheet.setRowCount(me.tree.items.length);
             me.initSelection(sheet.getActiveRowIndex());
         });
+    },
+    move: function (orgRow, newRow) {
+        this.workBook.getActiveSheet().deleteRows(orgRow, 1);
+        this.addRow(this.tree.items[newRow]);
     }
 };
 
 $(document).ready(function() {
     init();
     $('#tab_pm_all').on('show.bs.tab', function () {
-        gcTree = null;
+        gcTreeObj.tree = null;
         init();
     });
 
@@ -696,10 +719,14 @@ $(document).ready(function() {
             updateData = GetDeleteUpdateData(projTreeObj.tree.selected);
             UpdateProjectData(updateData, function () {
                 dialog.modal('hide');
+                //删除行号
+                let rIdx = projTreeObj.tree.items.indexOf(projTreeObj.tree.selected);
+                //删除行数
+                let rCout = projTreeObj.tree.selected.posterityCount() + 1;
                 projTreeObj.tree.removeNode(projTreeObj.tree.selected);
                 //delete view
                 let sheet = projTreeObj.workBook.getActiveSheet();
-                projTreeObj.remove(sheet);
+                projTreeObj.remove(sheet, rIdx, rCout);
             });
         }
     });
@@ -787,9 +814,18 @@ $(document).ready(function() {
                 projectType: null
             };
             updateData = GetUpdateData(null, parent, next, '', null, projTreeObj.tree.selected.id(), typeInfo);
+            //维护cur pre
+            let curPre = cur.preSibling();
+            if(curPre){
+                updateData.push({updateType: 'update', updateData: {ID: curPre.id(), NextSiblingID: cur.nid()}});
+            }
             UpdateProjectData(updateData, function (data) {
                 dialog.modal('hide');
+                let orgRow = projTreeObj.tree.items.indexOf(projTreeObj.tree.selected);
                 projTreeObj.tree.move(projTreeObj.tree.selected, parent, next);
+                let newRow = projTreeObj.tree.items.indexOf(projTreeObj.tree.selected);
+                //view move
+                projTreeObj.move(orgRow, newRow);
             });
         } else {
             dialog.modal('hide');
@@ -798,7 +834,7 @@ $(document).ready(function() {
 
     // 复制到按钮点击
     $('#copy-to-btn').click(function () {
-        let selectedItem = Tree.selected();
+        let selectedItem = projTreeObj.tree.selected;
         try {
             let selectedType = selectedItem !== null && selectedItem.data !== undefined ?
                 selectedItem.data.projType : '';
@@ -813,7 +849,7 @@ $(document).ready(function() {
     });
     // 复制到弹层替换
     $('#copy-to-dialog').on('show.bs.modal', function () {
-        copytoZTree = ConvertTreeToZtree(Tree, $('#treeDemo2'), null);
+        copytoZTree = ConvertTreeToZtree(projTreeObj.tree, $('#treeDemo2'), null);
     });
 
     // 复制到操作
@@ -823,7 +859,7 @@ $(document).ready(function() {
         let parent = null;
         let next = null;
         let pre = null;
-        let cur = Tree.selected();
+        let cur = projTreeObj.tree.selected;
         if (!target) {
             return false;
         }
@@ -874,15 +910,16 @@ $(document).ready(function() {
                     updateData = {};
                     updateData['updateType'] = 'update';
                     updateData['updateData'] = {};
-                    updateData['updateData'][Tree.setting.tree.id] = pre.id();
-                    updateData['updateData'][Tree.setting.tree.nid] = node.tree.maxNodeId() + 1;
+                    updateData['updateData'][projTreeObj.tree.setting.tree.id] = pre.id();
+                    updateData['updateData'][projTreeObj.tree.setting.tree.nid] = projTreeObj.tree.maxNodeId() + 1;
                 }
-                Tree.maxNodeId(IDs.lowID - 1);
+                console.log(updateData);
+                projTreeObj.tree.maxNodeId(IDs.lowID - 1);
                 CommonAjax.post('/pm/api/copyProjects', {updateData: updateData, user_id: userID}, function (data) {
                     dialog.modal('hide');
                     data.forEach(function (nodeData) {
                         if (nodeData.updateType === 'copy') {
-                            Tree.addNodeData(nodeData.updateData, parent, next);
+                            projTreeObj.insert(nodeData.updateData, parent, next);
                         }
                     });
                 }, function () {
@@ -930,7 +967,7 @@ function init() {
     //init spread and pmTree
     $.bootstrapLoading.start();
     GetAllProjectData(function (datas) {
-        projTreeObj.getShowData(datas);
+       // projTreeObj.getShowData(datas);
         projTreeObj.tree = pmTree.createNew(projTreeObj.setting, datas);
         projTreeObj.tree.selected = projTreeObj.tree.items[0];
         projTreeObj.buildSheet();
@@ -1073,20 +1110,20 @@ function AddTenderItems(selected, projName, engName, tenderName, property, callb
         GetNewProjectId(3, function (IDs) {
             let projID = IDs.lowID, engID = IDs.lowID + 1, tenderID = IDs.lowID + 2;
             if(!selected || selected.data.projType === projectType.project){
-                parent = selected ? selected.parent : Tree._root;
+                parent = selected ? selected.parent : projTreeObj.tree._root;
                 pre = selected;
-                next = selected ? selected.nextSibling : Tree.firstNode();
+                next = selected ? selected.nextSibling : projTreeObj.tree.firstNode();
             }
             else if(selected.data.projType === projectType.folder){
-                parent = selected ? selected : Tree._root;
-                pre = selected ? selected.lastChild() : Tree.firstNode();
+                parent = selected ? selected : projTreeObj.tree._root;
+                pre = selected ? selected.lastChild() : projTreeObj.tree.firstNode();
                 next = null;
             }
             else if(selected.data.projType === projectType.engineering || selected.data.projType === projectType.tender){
                 let selectedProj = selected.parent.data.projType === projectType.project ? selected.parent : selected.parent.parent;
-                parent = selectedProj ? selectedProj.parent : Tree._root;
+                parent = selectedProj ? selectedProj.parent : projTreeObj.tree._root;
                 pre = selectedProj;
-                next = selectedProj ? selectedProj.nextSibling : Tree.firstNode();
+                next = selectedProj ? selectedProj.nextSibling : projTreeObj.tree.firstNode();
             }
             let updateProjs = GetUpdateData(pre, parent, next, projName, null, projID, {updateType: 'new', projectType: projectType.project});
             let updateEng = {updateType: 'new', updateData: {ID: engID, ParentID: projID, NextSiblingID: -1, name: engName, projType: projectType.engineering}};
@@ -1290,7 +1327,7 @@ function getProjs(selected){
     let temp;
     let firstNode;
     if(!selected){
-        temp = projTreeObj.tree.roots;
+        temp = projTreeObj.tree._root;
         firstNode = temp.children[0];
     }
     else if(selected.data.projType === projectType.folder){
@@ -1311,17 +1348,19 @@ function getProjs(selected){
             rst.push(childNode);
         }
     }
-    //firstNode to first place
-    let index = null;
-    for(let i = 0, len = rst.length; i < len; i++){
-        if(rst[i].data.ID === firstNode.data.ID){
-            index = i;
-            break;
+    if(firstNode){
+        //firstNode to first place
+        let index = null;
+        for(let i = 0, len = rst.length; i < len; i++){
+            if(rst[i].data.ID === firstNode.data.ID){
+                index = i;
+                break;
+            }
+        }
+        if(index){
+            rst.splice(index, 1);
+            rst.splice(0, 0, firstNode);
         }
-    }
-    if(index){
-        rst.splice(index, 1);
-        rst.splice(0, 0, firstNode);
     }
     return rst;
 }
@@ -2109,8 +2148,8 @@ function bindEvents_file_table(jqS, usedObj, targetBody, type){
     $(jqS + ' p a:eq(1)').on('click', function () {
         let fileObjs = getFileObj(targetBody, type);
         let orgDispName = $(jqS + ' div:eq(0)')[0].childNodes[0].textContent;
-        let postFix = orgDispName.slice(orgDispName.length - 4, orgDispName.length);
-        let orgName = orgDispName.slice(0, orgDispName.length - 4);
+        let postFix = '';
+        let orgName = orgDispName;
         $(jqS + ' input').val(orgName);
         $(jqS + ' div:eq(0)').hide();
         $(jqS + ' div:eq(1)').show();
@@ -2118,6 +2157,7 @@ function bindEvents_file_table(jqS, usedObj, targetBody, type){
         $(jqS + ' .btn-success').on('click', function () {
             let attrId = $(jqS).attr('id');
             let id = attrId.slice(5, attrId.length);
+            console.log(id);
             let newName = $(jqS + ' input').val().trim();
             if(newName !== orgName){
                 if(hasThisFileName(fileObjs, newName)){
@@ -2148,6 +2188,8 @@ function bindEvents_file_table(jqS, usedObj, targetBody, type){
                     $(jqS + ' div:eq(0)')[0].childNodes[0].textContent = newDispName;
                     $(jqS + ' div:eq(0)').show();
                     $(jqS + ' div:eq(1)').hide();
+                    //refresh tender
+                    refreshTenderFile(getTendersByFile(type, id, projTreeObj.tree.selected), type, newName);
                 });
             }
             let newDispName = newName + postFix;
@@ -2241,3 +2283,37 @@ function hasThisFileName(fileObjs, name){
     }
     return false;
 }
+
+//获得使用此单价、费率文件的项目节点
+function getTendersByFile(type, fileId, project){
+    let rst = [];
+    let tenders = getProjTenders(project);
+    for(let tender of tenders){
+        if(type === fileType.unitPriceFile && tender.data.property && tender.data.property.unitPriceFile){
+            if(fileId == tender.data.property.unitPriceFile.id){
+                rst.push(tender);
+            }
+        }
+        else if(type === fileType.feeRateFile && tender.data.property && tender.data.property.feeFile){
+            if(fileId == tender.data.property.feeFile.id){
+                rst.push(tender);
+            }
+        }
+    }
+    return rst;
+}
+
+//重命名单价、费率文件后,刷新使用此文件的节点
+function refreshTenderFile(tenders, type, newName){
+   projTreeObj.renderSheetFuc(projTreeObj.workBook.getActiveSheet(), function () {
+       for(let tender of tenders){
+           if(type === fileType.unitPriceFile){
+               tender.data.property.unitPriceFile.name = newName;
+           }
+           else if(type === fileType.feeRateFile){
+               tender.data.property.feeFile.name = newName;
+           }
+           projTreeObj.refreshNodeData(tender);
+       }
+   });
+}

+ 0 - 1
web/building_saas/pm/js/pm_tree.js

@@ -319,7 +319,6 @@ const pmTree = {
                                 node.parent.children[iIndex - 1].setNextSibling(node.nextSibling);
                             }
                             node.parent.children.splice(iIndex, 1);
-                            this.refreshNodesDom([node.parent], false);
                         }
 
                         if (nextSibling) {