Przeglądaj źródła

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

chenshilong 7 lat temu
rodzic
commit
491d3d2f90

+ 3 - 2
config/gulpConfig.js

@@ -11,7 +11,8 @@ module.exports = {
         'lib/bootstrap/bootstrap.min.js',
         'web/building_saas/js/*.js',
         'public/web/scMathUtil.js',
-        'public/web/PerfectLoad.js'
+        'public/web/PerfectLoad.js',
+        'lib/lodash/lodash.js',
     ],
     common_css:[
         'lib/bootstrap/css/bootstrap.min.css',
@@ -47,7 +48,7 @@ module.exports = {
         'lib/jquery-ui/jquery-ui.min.js',
         'lib/jquery-ui/jquery-ui-datepickerCN.js',
         'lib/jquery-contextmenu/*.js',
-        'lib/lodash/lodash.js',
+        //'lib/lodash/lodash.js',
         // 'test/tmp_data/test_ration_calc/ration_calc_base.js',
         'web/building_saas/main/js/models/main_consts.js',
         'public/web/common_util.js',

+ 8 - 1
modules/fee_rates/facade/fee_rates_facade.js

@@ -31,7 +31,8 @@ module.exports={
     setFeeRateToBill:setFeeRateToBill,
     updateFeeRate:updateFeeRate,
     updateRates:update_rates,
-    feeRateFileSaveAs:feeRateFileSaveAs
+    feeRateFileSaveAs:feeRateFileSaveAs,
+    getFeeRateByID:getFeeRateByID
 };
 let operationMap={
     'ut_create':create_fee_rate,
@@ -405,4 +406,10 @@ async function changeFeeRateFileFromOthers(jdata) {
 
 async function getGCFeeRateFiles(userID){
     return await feeRateFileModel.find({userID: userID, 'deleteInfo.deleted': true});
+}
+
+async function getFeeRateByID(ID) {
+    let feeRateFile = await feeRateFileModel.findOne({'ID':ID});
+    let feeRate = await feeRateModel.findOne({ID:feeRateFile.feeRateID});
+    return [feeRateFile,feeRate]
 }

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

@@ -270,6 +270,8 @@ class GLJController extends BaseController {
                 // 归类
                 if (rootProjectID == projectList[index].ID) {
                     result.self = unitPriceFileData;
+                    result.currentProjectName =  projectList[index].name;
+
                 } else {
                     result.other.push(projectList[index]);
                 }

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

@@ -16,6 +16,7 @@ let projectModel = mongoose.model('projects');
 let unitPriceFileModel = mongoose.model('unit_price_file');
 let feeRateFileModel = mongoose.model('fee_rate_file');
 let asyncTool = require('async');
+let pm_facade = require('../facade/pm_facade');
 
 //统一回调函数
 let callback = function(req, res, err, message, data){
@@ -355,7 +356,7 @@ module.exports = {
         ProjectsData.recGC(userID, nodes, function (err, msg, data) {
             callback(request, response, err, msg, data);
         });
-    },
+   },
 
     delGC: async function(request, response){
         let data = JSON.parse(request.body.data);
@@ -386,6 +387,20 @@ module.exports = {
         }
         catch(err){
             callback(request, response, 1, err, null);
+        }    },
+moveProject:async function(req,res){
+        let result={
+            error:0
+        }
+        try {
+            let data = req.body.data;
+            let rdata= await pm_facade.moveProject(data);
+            result.data= rdata;
+        }catch (err){
+            console.log(err);
+            result.error=1;
+            result.message = err.message;
         }
+        res.json(result);
     }
 };

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

@@ -0,0 +1,179 @@
+/**
+ * Created by zhang on 2018/4/17.
+ */
+let mongoose = require('mongoose');
+let _ = require("lodash");
+let feeRate_facade = require('../../fee_rates/facade/fee_rates_facade');
+const uuidV1 = require('uuid/v1');
+let projectModel = mongoose.model('projects');
+let feeRateModel = mongoose.model('fee_rates');
+let feeRateFileModel = mongoose.model('fee_rate_file');
+let unitPriceFileModel = mongoose.model("unit_price_file");
+let mixRatioModel = mongoose.model("mix_ratio");
+let unitPriceModel = mongoose.model("unit_price");
+import CounterModel from "../../glj/models/counter_model";
+
+module.exports={
+    moveProject:moveProject  
+};
+
+async function moveProject(data) {
+    data = JSON.parse(data);
+    let projectMap = data.projectMap,feeRateMap = data.feeRateMap,unitPriceMap = data.unitPriceMap;
+    let projectTasks = [],feeRateTask=[],feeRateFileTask=[],unitPriceTask=[],unitPriceFileTask=[],mixRatioTask=[];
+    let feeUniqMap=[],priceUniqMap={};//费率、单价文件唯一映射表当移动多个项目时,任务有可能出现重复的情况
+    if(!_.isEmpty(feeRateMap)&&data.rootProjectID){//如果费率有修改
+        let feeRates =await feeRate_facade.getFeeRatesByProject(data.rootProjectID);//取目标建设项目的所有费率文件,重名检查
+        for(let projectID in feeRateMap){
+            let rename = feeRateMap[projectID].name;
+            let feeRateID =  feeRateMap[projectID].query.ID;
+            let checkFee = _.find(feeRates,{'name':rename});
+            let newID = feeRateID;
+            if(checkFee){//说明费率名字已存在,需要重命名
+                rename = feeUniqMap[feeRateID]?feeUniqMap[feeRateID].name:rename + '(' + new Date().Format('MM-dd hh:mm:ss') + '移动)';
+                projectMap[projectID]['update']['property.feeFile.name'] = rename;
+                if(feeRateMap[projectID].action == 'move'){
+                    feeRateMap[projectID].update.name = rename;
+                }
+            }
+            if(feeRateMap[projectID].action == 'copy'){
+                newID = feeUniqMap[feeRateID]?feeUniqMap[feeRateID].ID:uuidV1();
+                feeRateMap[projectID].name = rename;
+                feeRateMap[projectID].ID =  newID;
+                projectMap[projectID]['update']['property.feeFile.id'] = newID;
+            }
+            if(!feeUniqMap[feeRateID]){
+                await generateFeeRateTask(feeRateMap[projectID],feeRateTask,feeRateFileTask);
+                feeUniqMap[feeRateID] = {name:rename,ID:newID};
+            }
+        }
+    }
+    if(!_.isEmpty(unitPriceMap)&&data.rootProjectID) {//如果单价文件有修改
+        let unitPriceFiles =  await unitPriceFileModel.find({root_project_id: data.rootProjectID, deleteInfo: null});
+        for(let projectID in unitPriceMap){
+            let checkUn = _.find(unitPriceFiles,{'name':unitPriceMap[projectID].name});
+            let rename = unitPriceMap[projectID].name;
+            let unitPriceID = unitPriceMap[projectID].query.id;
+            let newID = unitPriceID;
+            if(checkUn){//重名检查
+                rename = priceUniqMap[unitPriceID]?priceUniqMap[unitPriceID].name:rename + '(' + new Date().Format('MM-dd hh:mm:ss') + '移动)';
+                projectMap[projectID]['update']['property.unitPriceFile.name'] = rename;
+                if(unitPriceMap[projectID].action =='move'){
+                    unitPriceMap[projectID].update.name = rename;
+                }
+            }
+            if(unitPriceMap[projectID].action =='copy'){
+                newID =  priceUniqMap[unitPriceID]?priceUniqMap[unitPriceID].id: await getCounterID("unit_price_file");
+                unitPriceMap[projectID].name = rename;
+                unitPriceMap[projectID].id = newID;
+                projectMap[projectID]['update']['property.unitPriceFile.id'] = newID;
+            }
+            if(!priceUniqMap[unitPriceID]){
+                await generateUnitPriceTask(unitPriceMap[projectID],projectID,data.user_id,unitPriceTask,unitPriceFileTask,mixRatioTask);
+                priceUniqMap[unitPriceID] = {name:rename,id:newID};
+            }
+        }
+    }
+
+    if(!_.isEmpty(projectMap)){
+        for(let projectID in projectMap){
+            projectTasks.push({updateOne:{filter : projectMap[projectID].query, update : projectMap[projectID].update}});
+        }
+    }
+
+    projectTasks.length>0?await projectModel.bulkWrite(projectTasks):'';
+    feeRateTask.length>0?await feeRateModel.bulkWrite(feeRateTask):'';
+    feeRateFileTask.length>0?await feeRateFileModel.bulkWrite(feeRateFileTask):'';
+    unitPriceFileTask.length>0?await unitPriceFileModel.bulkWrite(unitPriceFileTask):'';
+    unitPriceTask.length>0?await insertMany(unitPriceTask,unitPriceModel):'';
+    mixRatioTask.length>0?await insertMany(mixRatioTask,mixRatioModel):'';
+    return projectMap;
+}
+
+async function generateFeeRateTask(data,feeRateTask,feeRateFileTask) {
+    if(data.action == 'move'){
+        let task = {
+            updateOne:{
+                filter : data.query,
+                update : data.update
+            }
+        };
+        feeRateFileTask.push(task);
+    }
+    if(data.action == 'copy'){//copy 费率的时候用insertOne方法
+        let [feeRateFile,feeRate] =await feeRate_facade.getFeeRateByID(data.query.ID);
+        let newFeeRateID =  uuidV1();
+        let newFeeRate = {
+            ID:newFeeRateID,
+            rates:feeRate.rates
+        };
+        let newFeeRateFile = {
+            ID:data.ID,
+            rootProjectID:data.rootProjectID,
+            userID:feeRateFile.userID,
+            name:data.name,
+            libID:feeRateFile.libID,
+            libName:feeRateFile.libName,
+            feeRateID:newFeeRateID
+        };
+        feeRateTask.push({insertOne :{document:newFeeRate}});
+        feeRateFileTask.push({insertOne :{document:newFeeRateFile}});
+    }
+}
+
+async function generateUnitPriceTask(data,projectID,user_id,unitPriceTask,unitPriceFileTask,mixRatioTask){
+    if(data.action == 'move'){
+        let task = {
+            updateOne:{
+                filter : data.query,
+                update : data.update
+            }
+        };
+        unitPriceFileTask.push(task);
+    }
+    if(data.action == 'copy'){
+        let newUnitFile = {
+            id:data.id,
+            name: data.name,
+            project_id:projectID,
+            user_id:user_id,
+            root_project_id: data.rootProjectID
+        };
+        unitPriceFileTask.push({insertOne :{document:newUnitFile}});
+        let mixRatios = await mixRatioModel.find({unit_price_file_id: data.query.id});
+        mixRatios = JSON.stringify(mixRatios);
+        mixRatios = JSON.parse(mixRatios);
+        for(let m of mixRatios){
+            delete m._id;  // 删除原有id信息
+            delete m.id;
+            m.unit_price_file_id = data.id;
+            m.id = await getCounterID('mix_ratio');
+            mixRatioTask.push(m);
+        }
+        let unitPrices = await unitPriceModel.find({unit_price_file_id: data.query.id});//unit_price_file_id
+        unitPrices = JSON.stringify(unitPrices);
+        unitPrices = JSON.parse(unitPrices);
+        for(let u of unitPrices){
+            delete u._id;  // 删除原有id信息
+            delete u.id;
+            u.unit_price_file_id = data.id;
+            u.id = await getCounterID('unit_price');
+            unitPriceTask.push(u);
+        }
+    }
+}
+
+
+async function getCounterID(collectionName){
+    let counterModel = new CounterModel();
+    return  await counterModel.getId(collectionName);
+}
+
+async function insertMany(datas,model) {
+    while (datas.length>1000){//因为mongoose限制了批量插入的条数为1000.所以超出限制后需要分批插入
+        let newList = datas.splice(0,1000);//一次插入1000条
+        model.insertMany(newList);
+    }
+    model.insertMany(datas);
+
+}

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

@@ -90,6 +90,7 @@ ProjectsDAO.prototype.updateUserProjects = async function (userId, compilationId
             callback(1, '提交数据出错.', null);
         }
     };
+    console.log(datas);
     if (datas) {
         for (i = 0; i < datas.length && !hasError; i++) {
             data = datas[i];

+ 1 - 0
modules/pm/routes/pm_route.js

@@ -32,6 +32,7 @@ module.exports = function (app) {
      */
     pmRouter.post('/updateProjects', pmController.updateProjects);
     pmRouter.post('/updateMixDatas', pmController.updateMixDatas);
+    pmRouter.post('/moveProject', pmController.moveProject);
 
     /*
      req.body = {data: '{user_id: user_id, updateData: [{updateType, updateData}]}'}

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

@@ -44,12 +44,12 @@
             <div class="modal-body">
                 <div class="form-group">
                     <label class="custom-control custom-radio">
-                        <input id="radio1" name="chaneg-lv-Radio" type="radio" value="0" onclick="changeFRadioClick()" class="custom-control-input" checked>
+                        <input id="radio1" name="chaneg-lv-Radio" type="radio" value="0" onclick="changeFRadioClick()" class="" checked>
                         <span class="custom-control-indicator"></span>
                         <span class="custom-control-description">从本建设项目中选择</span>
                     </label>
                     <label class="custom-control custom-radio">
-                        <input id="radio2" name="chaneg-lv-Radio" type="radio" value="1" onclick="changeFRadioClick()" class="custom-control-input">
+                        <input id="radio2" name="chaneg-lv-Radio" type="radio" value="1" onclick="changeFRadioClick()" class="">
                         <span class="custom-control-indicator"></span>
                         <span class="custom-control-description">从其他建设项目中复制</span>
                     </label>

+ 2 - 2
web/building_saas/glj/html/project_glj.html

@@ -63,12 +63,12 @@
             <div class="modal-body">
                 <div class="form-group">
                     <label class="custom-control custom-radio">
-                        <input name="change-type" type="radio" class="custom-control-input" checked="checked" value="0">
+                        <input name="change-type" type="radio" class="" checked="checked" value="0">
                         <span class="custom-control-indicator"></span>
                         <span class="custom-control-description">从本建设项目中选择</span>
                     </label>
                     <label class="custom-control custom-radio">
-                        <input name="change-type" type="radio" class="custom-control-input" value="1">
+                        <input name="change-type" type="radio" class="" value="1">
                         <span class="custom-control-indicator"></span>
                         <span class="custom-control-description">从其他建设项目中复制</span>
                     </label>

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

@@ -1085,7 +1085,7 @@
         <script type="text/javascript" src="/lib/jquery-ui/jquery-ui-datepickerCN.js"></script>
         <script type="text/javascript" src="/lib/jquery-contextmenu/jquery.contextMenu.js"></script>
         <script type="text/javascript" src="/lib/jquery-contextmenu/jquery.ui.position.js"></script>
-        <script type="text/javascript" src="/lib/lodash/lodash.js"></script>
+        <!--<script type="text/javascript" src="/lib/lodash/lodash.js"></script>-->
     <!-- Common -->
         <script type="text/javascript" src="/public/web/common_ajax.js"></script>
         <script type="text/javascript" src="/public/web/url_util.js"></script>

+ 1 - 4
web/building_saas/main/js/views/project_glj_view.js

@@ -539,10 +539,6 @@ $(function () {
     );
     // 单价文件切换弹框
     $('#change-unitFile').on('shown.bs.modal', function () {
-        // 获取当前建设项数据
-        let projectName = projectInfoObj.projectInfo.fullFolder !== undefined &&
-        projectInfoObj.projectInfo.fullFolder.length > 0 ? projectInfoObj.projectInfo.fullFolder[0] : '';
-        $("#current-project-name").text(projectName);
         let rootProjectID = projectInfoObj.projectInfo.property.rootProjectID;
         // 获取切换单价文件相关数据
         $.ajax({
@@ -556,6 +552,7 @@ $(function () {
                     return false;
                 }
                 let data = response.data;
+                $("#current-project-name").text(data.currentProjectName);
                 // 本项目中的单价文件
                 if (data.self.length > 0) {
                     let selfFileHtml = '';

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

@@ -1161,7 +1161,7 @@ var projectObj = {
             }
         });
      
-},
+    },
     loadLockBillsButton:function () {
         if(projectInfoObj.projectInfo.property.lockBills == true){
             $("a[name='lockBills']").prop("title","解锁清单");

+ 38 - 0
web/building_saas/pm/js/pm_ajax.js

@@ -85,4 +85,42 @@ var BeforeOpenProject = function (projId, updateData, callback) {
             alert('error ' + textStatus + " " + errorThrown)
         }
     });
+}
+
+var CommonAjax = {
+    get: function (url, data, cb, dataType) {
+        $.get(url, data, cb, dataType)
+    },
+    post: function (url, data, successCallback, errorCallback) {
+        $.ajax({
+            type: "POST",
+            url: url,
+            data: {'data': JSON.stringify(data)},
+            dataType: 'json',
+            cache: false,
+            timeout: 50000,
+            success: function (result) {
+                if (result.error === 0) {
+                    if (successCallback) {
+                        successCallback(result.data);
+                    }
+                } else {
+                    alert('error: ' + result.message);
+                    if (errorCallback) {
+                        errorCallback();
+                    }
+                }
+            },
+            error: function (jqXHR, textStatus, errorThrown) {
+                alert('url: ' + url + ' error ' + textStatus + " " + errorThrown);
+                if (errorCallback) {
+                    errorCallback();
+                }
+            }
+        });
+    }
+}
+
+function moveProjects(data,callback) {
+    CommonAjax.post( '/pm/api/moveProject',data,callback)
 }

+ 217 - 3
web/building_saas/pm/js/pm_newMain.js

@@ -52,9 +52,10 @@ const projTreeObj = {
             tabStripVisible:  false,
             allowCopyPasteExcelStyle : false,
             allowExtendPasteRange: false,
-            allowUserDragDrop : false,
+            allowUserDragDrop : true,
             allowUserDragFill: false,
-            scrollbarMaxAlign : true
+            scrollbarMaxAlign : true,
+            showDragDropTip:false
         }
     },
     renderSheetFuc: function (sheet, fuc) {
@@ -74,11 +75,14 @@ const projTreeObj = {
         let sheet = workBook.getActiveSheet();
         //改变选中节点set selected
         sheet.bind(_events.SelectionChanging, this.onSelectionChanging);
+        sheet.bind(_events.EditStarting, this.onCellEditing);
+        sheet.bind(_events.ClipboardPasting,this.onCellEditing);
+        workBook.bind(_events.DragDropBlock, this.onDragDropBlock);
     },
     buildHeader: function (sheet, headers) {
         let me = this;
         let fuc = function () {
-            sheet.options.isProtected = true;
+            //sheet.options.isProtected = true;  //为了拖动功能,这里不设置protect,输入限制在editstarting控制
             sheet.options.protectionOptions = {
                 allowResizeRows: true,
                 allowResizeColumns: true
@@ -169,6 +173,181 @@ const projTreeObj = {
         let me = projTreeObj;
         me.initSelection(args.newSelections[0], args.oldSelections[0]);
     },
+    onDragDropBlock : function (sender,args) {//拖动移动项目位置
+        console.log(args);
+        let selected = projTreeObj.tree.selected;
+        let targetNode = projTreeObj.tree.items[args.toRow];
+        let projectMap = {},feeRateMap={},unitPriceMap = {},parent=null,next = null;
+        let rootProjectID = null;//记录建设项目ID
+        //let updateObj = {project:[],feeRateFile:[],unitPriceFile:[]};
+        args.cancel = true;//首先取消填充的动作
+        if(selected.preSibling()!=null&&selected.preSibling() == targetNode){
+            return;
+        }
+
+        if(selected.data.projType=="Tender"){//移动单位工程
+            if(targetNode.data.projType=="Tender"||targetNode.data.projType=="Engineering"){//只能移动到这两个地方
+                if(targetNode.data.projType=="Tender"){//移动到单位工程后面
+                    [parent,next] = getMoveUpdateData(selected,targetNode,projectMap,true);
+                    rootProjectID = targetNode.parent.pid();
+                }else{//移动后成为单项工程的子项
+                    [parent,next] =getMoveUpdateData(selected,targetNode,projectMap,false);
+                    rootProjectID = targetNode.pid();
+                }
+                if(selected.data.property.rootProjectID != rootProjectID){//如果不属于同一个建设项目,要检查是否移动或复制单价文件和费率文件
+                    projectMap[selected.id()].update['property.rootProjectID'] = rootProjectID; //要改变根项目ID
+                    //检查费率文件和单价文件
+                    moveOrCopy(selected,rootProjectID,feeRateMap,unitPriceMap,false);
+                }
+            }
+        }
+        if(selected.data.projType=="Engineering"){//移动的是单项工程
+            if(targetNode.data.projType=="Engineering"||targetNode.data.projType=="Project"){//目标位置是单项工程和建设项目
+                if(targetNode.data.projType=="Engineering"){
+                    [parent,next] = getMoveUpdateData(selected,targetNode,projectMap,true);
+                    rootProjectID = targetNode.pid();
+                }else {
+                    [parent,next]  = getMoveUpdateData(selected,targetNode,projectMap,false);
+                    rootProjectID = targetNode.id();
+                }
+                if(selected.pid() != rootProjectID){//跨了建设项目,更新子项目,同时要检查是否移动或复制子项的单价文件和费率文件。
+                    //检查费率文件和单价文件
+                    //todo
+                    for(let c of selected.children){
+                        projectMap[c.id()] = {query:{'ID':c.id()},update:{'property.rootProjectID':rootProjectID}};
+                        moveOrCopy(c,rootProjectID,feeRateMap,unitPriceMap,true);
+                    }
+                }
+            }
+        }
+        if(selected.data.projType=="Project"){//移动的是建设项目
+            if(targetNode.data.projType=="Project"||targetNode.data.projType=="Folder") {//目标位置是建设项目和文件夹
+                if(targetNode.data.projType=="Project"){
+                    [parent,next]  = getMoveUpdateData(selected,targetNode,projectMap,true);
+                }else {
+                    [parent,next]  = getMoveUpdateData(selected,targetNode,projectMap,false);
+                }
+            }
+        }
+        if(selected.data.projType=="Folder"&&targetNode.data.projType=="Folder") {//文件夹只能移动到文件夹下
+            [parent,next]  =  getMoveUpdateData(selected,targetNode,projectMap,false);//成为子项
+        }
+        if(_.isEmpty(projectMap)){//项目数据为空
+            return;
+        }
+        $.bootstrapLoading.start();
+        moveProjects({"user_id": userID,rootProjectID:rootProjectID,projectMap:projectMap,feeRateMap:feeRateMap,unitPriceMap:unitPriceMap},function (result) {
+            console.log(result);
+            for(let key in result){//更新前端节点数据
+                let updateData = result[key].update;
+                let node = projTreeObj.tree.findNode(result[key].query.ID);
+                if(node){
+                    console.log(node.data);
+                    for(let ukey in updateData){
+                        _.set(node.data,ukey,updateData[ukey]);
+                    }
+                    console.log(node.data);
+                }
+            }
+            projTreeObj.moveTo(selected,targetNode,parent,next);
+            $.bootstrapLoading.end();
+        });
+      //  projTreeObj.moveTo(selected,targetNode,parent,next);
+        //删除行数
+
+
+        function getMoveUpdateData(sel,target,projectMap,sameLevel) {
+            let tem_parent = null,tem_next = null;
+            if(sameLevel==true){//移动后的位置的级别相同
+                tem_parent = target.parent;
+                tem_next = target.nextSibling;
+                //移动到target的后面
+                projectMap[target.id()] = {query:{'ID':target.id()},update:{'NextSiblingID':sel.id()}};
+                console.log(target.id()+'----'+target.data.name);
+            }else {//移动后变成子项
+                tem_parent = target;
+                tem_next = target.firstChild();
+            }
+            let nextID = tem_next?tem_next.id():-1;
+            if(sel.preSibling() != null){//如果原来有前项,更新下一节点
+                projectMap[sel.preSibling().id()] = {query:{'ID':sel.preSibling().id()},update:{'NextSiblingID':sel.data.NextSiblingID}};
+                console.log(sel.preSibling().id()+'----'+sel.preSibling().data.name);
+            }
+            if(sel.parent.id() == tem_parent.id()){//移动前移动后的父项相同,只改变next
+                projectMap[selected.id()] = {query:{'ID':selected.id()},update:{'NextSiblingID':nextID}};
+                console.log(selected.id()+'----'+selected.data.name);
+            }else {//
+                let temData = {query:{'ID':selected.id()},update:{'ParentID':tem_parent.id(),'NextSiblingID':nextID}};
+                let reName = projTreeObj.projectNameChecking(tem_parent,selected);//重名检查
+                if(reName){
+                    temData.update['name'] = reName
+                }
+                projectMap[selected.id()] = temData;
+                console.log(selected.id()+'----'+selected.data.name);
+            }
+            return [tem_parent,tem_next]
+        }
+
+        function moveOrCopy(sel,rootProjectID,feeRateMap,unitPriceMap,sameCheck) {//检查选中的项目使用的费率文件和单价文件是要移动还是复制一份
+            let project = sel.parent.parent;//取建设项目
+            let sameParent_f = true;
+            let sameParent_u = true;
+            let useFeeRateProject = getTendersByFile(fileType.feeRateFile,sel.data.property.feeFile.id,project);
+            let useUnitPriceProject = getTendersByFile(fileType.unitPriceFile,sel.data.property.unitPriceFile.id,project);
+            let tem_feeRate = {action:'copy',rootProjectID:rootProjectID,name:sel.data.property.feeFile.name,query:{ID:sel.data.property.feeFile.id}};
+            let tem_unitPrice = {action:'copy',rootProjectID:rootProjectID,name:sel.data.property.unitPriceFile.name,query:{id:sel.data.property.unitPriceFile.id}}
+            if(useFeeRateProject.length==1){//如果没有其它项目使用同一个费率文件,则移动
+                tem_feeRate.action = 'move';
+                tem_feeRate.update = {rootProjectID:rootProjectID};
+            }
+            if(useUnitPriceProject.length == 1){//如果没有其它项目使用同一个单价文件,则移动
+                tem_unitPrice.action =  'move';
+                tem_unitPrice.update = {root_project_id:rootProjectID};
+            }
+            feeRateMap[sel.id()] = tem_feeRate;
+            unitPriceMap[sel.id()] = tem_unitPrice;
+            if(sameCheck == true){//需要检查是否属于同一个单项工程,移动单项工程的时候用
+                if(useUnitPriceProject.length > 1){
+                    for(let f of useFeeRateProject){
+                        if(f.pid()!=sel.pid()){//父节点不同
+                            sameParent_f = false;
+                            break;
+                        }
+                    }
+                    if(sameParent_f == true){//如果使用的都是同属于一个单项工程,在移动单项工程的时候,移动费率文件和单价文件就可以了
+                        feeRateMap[sel.id()].action = 'move';
+                        feeRateMap[sel.id()].update = {rootProjectID:rootProjectID};
+                    }
+                }
+                if(useUnitPriceProject.length > 1){
+                    for(let u of useUnitPriceProject){
+                        if(u.pid()!=sel.pid()){//父节点不同
+                            sameParent_u = false;
+                            break;
+                        }
+                    }
+                    if(sameParent_u == true){
+                        unitPriceMap[sel.id()].action =  'move';
+                        unitPriceMap[sel.id()].update = {root_project_id:rootProjectID};
+                    }
+                }
+            }
+        }
+
+
+    },
+    projectNameChecking:function (parent,node) {
+        //decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
+        for(let c of parent.children){
+           if(c.data.name == node.data.name){//如果存在同名的项目
+               return  node.data.name + '(' + new Date().Format('MM-dd hh:mm:ss') + '移动)';
+           }
+        }
+        return null;
+    },
+    onCellEditing:function (sender,args) {
+        args.cancel = true;
+    },
     getShowData: function (datas) {
         for(let data of datas){
             data.name = data.name ? data.name : '';
@@ -457,6 +636,7 @@ const projTreeObj = {
                     let dataCode = headers[j].dataCode;
                     //sheet.setValue(i, j, nodes[i]['data'][dataCode]);
                 }
+                sheet.getCell(i, 1,GC.Spread.Sheets.SheetArea.viewport).locked(true);
             }
         };
         me.renderSheetFuc(sheet, fuc);
@@ -509,6 +689,40 @@ const projTreeObj = {
     move: function (orgRow, newRow) {
         this.workBook.getActiveSheet().deleteRows(orgRow, 1);
         this.addRow(this.tree.items[newRow]);
+    },
+    moveTo : function(select,target,parent,next){
+        let me = this;
+        let fromRow = select.serialNo();
+        let rCout = select.posterityCount() + 1;//删除的行数
+        let toRow = target.serialNo();
+        let sheet = me.workBook.getActiveSheet();
+        me.tree.removeNode(select);//删除旧节点
+        let newNode  = addNewNodes(select, parent, next);
+       // projTreeObj.remove(sheet, fromRow, rCout);
+
+        me.renderSheetFuc(sheet, function () {
+            sheet.deleteRows(fromRow, rCout);
+            sheet.addRows(newNode.serialNo(),rCout);
+            let oldSelection = sheet.getSelections()[0];
+            let newSelection = {row: newNode.serialNo(), rowCount: 1,col:oldSelection.col,colCount:oldSelection.colCount};
+            me.initSelection({row: newNode.serialNo(), rowCount: oldSelection.rowCount}, oldSelection);
+            sheet.setSelection(newNode.serialNo(),oldSelection.col,oldSelection.rowCount,oldSelection.colCount);
+            let children = newNode.getAllChildren();
+            children.push(newNode);
+            for(let c of children){
+                sheet.getCell(c.serialNo(), 0).cellType(me.getTreeNodeCell(me.tree));
+                me.refreshNodeData(c);
+            }
+        });
+
+        function addNewNodes(node,parent,next) {
+            let newNode = me.tree.addNodeData(node.data, parent, next);
+            for(let c of node.children){
+                addNewNodes(c,newNode,null);
+            }
+            return newNode;
+        }
+
     }
 };
 

+ 12 - 2
web/building_saas/pm/js/pm_tree.js

@@ -157,8 +157,18 @@ const pmTree = {
 
             Node.prototype.propertyJoin = function (dataName) {
                 return this.parent ? this.parent.propertyJoin(dataName) + ';' + this.data[dataName] : this.data[dataName];
-            }
-
+            };
+            Node.prototype.getAllChildren = function () {
+                let childrenList = [];
+                getChildren(this);
+                function getChildren(node) {
+                    for(let c of node.children){
+                        childrenList.push(c);
+                        getChildren(c)
+                    }
+                }
+                return childrenList;
+            };
             return Node;
         })();
 

+ 1 - 0
web/common/html/header.html

@@ -93,4 +93,5 @@
 <script type="text/javascript" src="/web/building_saas/js/message.js"></script>
 <script type="text/javascript" src="/public/web/scMathUtil.js"></script>
 <script type="text/javascript" src="/public/web/PerfectLoad.js"></script>
+<script type="text/javascript" src="/lib/lodash/lodash.js"></script>
 <!-- endinject -->