Przeglądaj źródła

导入导出功能

zhangweicheng 6 lat temu
rodzic
commit
5f6b0bd06e

+ 9 - 21
modules/pm/controllers/pm_controller.js

@@ -683,36 +683,24 @@ module.exports = {
 
     },
     importProject:async function(req,res){
-        let form = new multiparty.Form({uploadDir: './public'});
+        let form = new multiparty.Form({uploadDir: './tmp'});
         let uploadFullName;
         form.parse(req, async function (err, fields, files) {
             try {
+                console.log(fields);
                 const file = typeof files.file !== 'undefined' ? files.file[0] : null;
                 if (err || !file) {
                     throw '上传失败。';
-                }
-                console.log(file);
+                };
                 let data = fs.readFileSync(file.path,'utf-8');
-                console.log(data);
+                let result = await pm_facade.importProject(data,req,fields);
+                fs.unlinkSync(file.path);
+                res.json(result);
             }catch (e){
-
+                console.log(e);
+                res.json({error:1,msg:"导入失败请检查文件!"})
             }
-            res.json({error:0})
-        })
-        /*let result={
-            error:0
-        };
-        try {
-            console.log(req.files[0]);
-           /!* let data = JSON.parse(req.body.data);
-            result.data = await pm_facade.exportProject(req.session.sessionUser.id, data);*!/
-        }catch (err){
-            console.log(err);
-            result.error=1;
-            result.message = err.message;
-        }
-        res.json(result);*/
-
 
+        })
     }
 };

+ 304 - 25
modules/pm/facade/pm_facade.js

@@ -27,7 +27,8 @@ module.exports={
     prepareInitialData: prepareInitialData,
     changeFile:changeFile,
     copyForSectionError: copyForSectionError,
-    exportProject:exportProject
+    exportProject:exportProject,
+    importProject:importProject
 };
 
 
@@ -293,35 +294,34 @@ async function copyProjectSetting(originalID,newProjectID) {
 async function copyBills(newProjectID,billMap) {
      let uuidMaping = billMap.uuidMaping;//做ID映射
      for(let doc of billMap.datas){
-         doc.projectID = newProjectID;
-         doc.ID = uuidMaping[doc.ID] ? uuidMaping[doc.ID] : -1;
-         doc.ParentID = uuidMaping[doc.ParentID] ? uuidMaping[doc.ParentID] : -1;
-         doc.NextSiblingID = uuidMaping[doc.NextSiblingID] ? uuidMaping[doc.NextSiblingID] : -1;
-         //对于有基数计算的节点,需要替换计算基数中引用的ID为新的ID
-         if(doc.calcBase && doc.calcBase != ""){
-             let idArr = scMathUtil.getFIDArr(doc.calcBase);
-             for(let re of idArr){
-                 let oID = re.substr(1);//去掉开头的@字符
-                 if(!uuidMaping[oID]) continue;
-                 doc.calcBase = doc.calcBase.replace(new RegExp(oID, "g"),uuidMaping[oID]);
-             }
-         }
+         doc = getCopyBillDatas(doc,newProjectID,uuidMaping)
      }
     await insertMany(billMap.datas,billsModel);
     return billMap.datas;
 }
 
+
+function getCopyBillDatas(doc,newProjectID,uuidMaping) {
+    doc.projectID = newProjectID;
+    doc.ID = uuidMaping[doc.ID] ? uuidMaping[doc.ID] : -1;
+    doc.ParentID = uuidMaping[doc.ParentID] ? uuidMaping[doc.ParentID] : -1;
+    doc.NextSiblingID = uuidMaping[doc.NextSiblingID] ? uuidMaping[doc.NextSiblingID] : -1;
+    //对于有基数计算的节点,需要替换计算基数中引用的ID为新的ID
+    if(doc.calcBase && doc.calcBase != ""){
+        let idArr = scMathUtil.getFIDArr(doc.calcBase);
+        for(let re of idArr){
+            let oID = re.substr(1);//去掉开头的@字符
+            if(!uuidMaping[oID]) continue;
+            doc.calcBase = doc.calcBase.replace(new RegExp(oID, "g"),uuidMaping[oID]);
+        }
+    }
+    return doc;
+}
+
 async function copyRations(newProjectID,billsIDMap,rationMap,projectGLJIDMap) {
     let uuidMaping = rationMap.uuidMaping;
     for(let doc of rationMap.datas){
-        doc.projectID = newProjectID;
-        doc.ID = uuidMaping[doc.ID] ? uuidMaping[doc.ID] : -1;
-        if(doc.billsItemID){
-            doc.billsItemID = billsIDMap[doc.billsItemID]?billsIDMap[doc.billsItemID]:-1;
-        }
-        if(doc.referenceRationID) doc.referenceRationID = uuidMaping[doc.referenceRationID]?uuidMaping[doc.referenceRationID]:undefined;
-        //绑定定类型的工料机 项目工料机ID
-        doc.type==3&&doc.projectGLJID&&projectGLJIDMap[doc.projectGLJID]?doc.projectGLJID = projectGLJIDMap[doc.projectGLJID]:'';
+        doc = getCopyRationData(doc,newProjectID,billsIDMap,uuidMaping,projectGLJIDMap);
     }
     if(rationMap.datas.length > 0){
         await insertMany(rationMap.datas,rationModel);
@@ -329,6 +329,20 @@ async function copyRations(newProjectID,billsIDMap,rationMap,projectGLJIDMap) {
     return rationMap.datas;
 }
 
+
+function getCopyRationData(doc,newProjectID,billsIDMap,uuidMaping,projectGLJIDMap){
+    doc.projectID = newProjectID;
+    doc.ID = uuidMaping[doc.ID] ? uuidMaping[doc.ID] : -1;
+    if(doc.billsItemID){
+        doc.billsItemID = billsIDMap[doc.billsItemID]?billsIDMap[doc.billsItemID]:-1;
+    }
+    if(doc.referenceRationID) doc.referenceRationID = uuidMaping[doc.referenceRationID]?uuidMaping[doc.referenceRationID]:undefined;
+    //绑定定类型的工料机 项目工料机ID
+    doc.type==3&&doc.projectGLJID&&projectGLJIDMap[doc.projectGLJID]?doc.projectGLJID = projectGLJIDMap[doc.projectGLJID]:'';
+    return doc;
+}
+
+
 async function copyProjectGLJ(gljList) {
     await insertMany(gljList,gljListModel);
 }
@@ -416,7 +430,8 @@ async function copyRationSubList(originalPID,newProjectID,billIDMap,rationIDMap,
     let subList = await model.find({projectID:originalPID}, '-_id');
     let newList =[];
     for(let s of subList){
-        s._doc.ID = uuidV1();
+        s._doc = getCopyRationSubData(s._doc,newProjectID,billIDMap,rationIDMap,projectGLJIDMap);
+   /*     s._doc.ID = uuidV1();
         s._doc.projectID = newProjectID;
         s._doc.rationID&&rationIDMap[s._doc.rationID]?s._doc.rationID = rationIDMap[s._doc.rationID]:'';
         s._doc.billID&&billIDMap[s._doc.billID]?s._doc.billID = billIDMap[s._doc.billID]:'';
@@ -427,12 +442,30 @@ async function copyRationSubList(originalPID,newProjectID,billIDMap,rationIDMap,
                 if(t.billID && billIDMap[t.billID]) t.billID =  billIDMap[t.billID];
                 if(t.fxID && billIDMap[t.fxID]) t.fxID =  billIDMap[t.fxID];
             }
-        }
+        }*/
         newList.push(s._doc);
     }
     await insertMany(newList,model);
 }
 
+function getCopyRationSubData(doc,newProjectID,billIDMap,rationIDMap,projectGLJIDMap){
+    doc.ID = uuidV1();
+    doc.projectID = newProjectID;
+    doc.rationID&&rationIDMap[doc.rationID]?doc.rationID = rationIDMap[doc.rationID]:'';
+    doc.billID&&billIDMap[doc.billID]?doc.billID = billIDMap[doc.billID]:'';
+    doc.billsItemID&&billIDMap[doc.billsItemID]?doc.billsItemID = billIDMap[doc.billsItemID]:'';
+    doc.projectGLJID&&projectGLJIDMap[doc.projectGLJID]?doc.projectGLJID = projectGLJIDMap[doc.projectGLJID]:'';
+    if(doc.templateList && doc.templateList.length > 0 ){
+        for(let t of doc.templateList){
+            if(t.billID && billIDMap[t.billID]) t.billID =  billIDMap[t.billID];
+            if(t.fxID && billIDMap[t.fxID]) t.fxID =  billIDMap[t.fxID];
+        }
+    }
+    return doc;
+}
+
+
+
 async function moveProject(data) {
     data = JSON.parse(data);
     let projectMap = data.projectMap,feeRateMap = data.feeRateMap,unitPriceMap = data.unitPriceMap;
@@ -465,7 +498,7 @@ async function moveProject(data) {
         }
     }
     if(!_.isEmpty(unitPriceMap)&&data.rootProjectID) {//如果单价文件有修改
-        let unitPriceFiles =  await unitPriceFileModel.find({root_project_id: data.rootProjectID, deleteInfo: null});
+        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;
@@ -1054,4 +1087,250 @@ async function exportTenderData(data){
     result.labourCoes = await labourCoesModel.findOne({projectID:data.projectID});
 
     return cipher.aesEncrypt(JSON.stringify(result));
+}
+
+
+async function importProject(data,req,fields) {
+    let result = {error:0};
+    let stringArr = data.split("|----|");
+    let datas = [];
+    for(let s of stringArr){
+        datas.push(JSON.parse(cipher.aesDecrypt(s)));
+    }
+    let mainData = datas.length > 0 ?datas[0]:null;
+    if(mainData){
+         if(mainData.compilationID != req.session.sessionCompilation._id){
+             result.error = 1;
+             result.msg = "编办不同,无法导入,请重新选择!";
+         }else {
+            let [projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap] = await handleMainProjectDatas(mainData,JSON.parse(fields.updateData[0]),req.session.sessionUser.id);
+            if(datas.length > 1 ){
+                for(let i = 1;i<datas.length;i++){
+                    await handleEachProject(datas[i],projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap)
+                }
+            }
+
+         }
+    }
+    return result;
+}
+
+async function handleEachProject(data,projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap){
+    let bills = [],rations = [],projectGLJs = [],rationGLJs=[],rationCoes=[],quantityDetails=[],rationInstallations=[],rationTemplates=[];
+    let newProjectSetting =null,newCalcProgramsFile = null,newLabourCoe = null;
+    let billsIDMap = {},projectGLJIDMap={},rationIDMap = {};
+    let newProjectID = projectIDMap[data.projSetting.projectID];
+    //生成新的清单;
+    if(data.bills && data.bills.length > 0){
+        for(let b of data.bills){
+            billsIDMap[b.ID] = uuidV1();
+        }
+        for(let b of data.bills){
+            delete b._id;
+            b = getCopyBillDatas(b,newProjectID,billsIDMap);
+            bills.push(b);
+        }
+    }
+
+    //生成项目工料机数据
+    if(data.projectGLJs && data.projectGLJs.length > 0){
+        let gljCount = await counter.counterDAO.getIDAfterCountSync(counter.moduleName.glj_list, data.projectGLJs.length);
+        for(let i = 0; i < data.projectGLJs.length; i++){
+            let d = data.projectGLJs[i];
+            delete d._id;
+            let newID = gljCount.sequence_value - (data.projectGLJs.length - 1) + i;
+            projectGLJIDMap[d.id] = newID;
+            d.project_id = newProjectID;
+            d.id = newID;
+            projectGLJs.push(d);
+        }
+    }
+
+    //生成新的定额
+    if(data.rations && data.rations.length > 0){
+        for(let r of data.rations){
+            rationIDMap[r.ID] = uuidV1();
+        }
+        for(let r of data.rations){
+            delete r._id;
+            r = getCopyRationData(r,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
+            rations.push(r);
+        }
+    }
+
+    //生成定额下挂的定额工料机等等数据
+    if(data.rationGLJs && data.rationGLJs.length > 0) rationGLJs = setRationSubList(data.rationGLJs,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
+    if(data.rationCoes && data.rationCoes.length > 0) rationCoes = setRationSubList(data.rationCoes,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
+    if(data.quantityDetails && data.quantityDetails.length > 0) quantityDetails = setRationSubList(data.quantityDetails,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
+    if(data.rationInstallations && data.rationInstallations.length > 0) rationInstallations = setRationSubList(data.rationInstallations,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
+    if(data.rationTemplates && data.rationTemplates.length > 0) rationTemplates = setRationSubList(data.rationTemplates,newProjectID,billsIDMap,rationIDMap,projectGLJIDMap);
+
+    //生成projectSetting 文件
+    if(data.projSetting){
+        data.projSetting.projectID =newProjectID;
+        newProjectSetting = data.projSetting;
+        delete newProjectSetting._id;
+    }
+
+    //生成计算程序文件,系数文件
+    if(data.calcProgramsFile && calcProgramFileIDMap[data.calcProgramsFile.ID]){
+        data.calcProgramsFile.ID = calcProgramFileIDMap[data.calcProgramsFile.ID];
+        data.calcProgramsFile.projectID = newProjectID;
+        newCalcProgramsFile =  data.calcProgramsFile;
+        delete newCalcProgramsFile._id;
+
+    }
+    if(data.labourCoes && labourCoeFileIDMap[data.labourCoes.ID]){
+        data.labourCoes.ID = labourCoeFileIDMap[data.labourCoes.ID];
+        data.labourCoes.projectID = newProjectID;
+        newLabourCoe = data.labourCoes;
+        delete newLabourCoe._id;
+    }
+
+    if(newProjectSetting) await projectSettingModel.create(newProjectSetting);
+    if(bills.length > 0) await insertMany(bills,billsModel);
+    if(rations.length > 0) await insertMany(rations,rationModel);
+    if(projectGLJs.length > 0) await insertMany(projectGLJs,gljListModel);
+    if(rationGLJs.length > 0) await insertMany(rationGLJs,rationGLJModel);
+    if(rationCoes.length > 0) await insertMany(rationCoes,rationCoeModel);
+    if(quantityDetails.length > 0) await insertMany(quantityDetails,quantityDetailModel);
+    if(rationInstallations.length > 0) await insertMany(rationInstallations,rationInstallationModel);
+    if(rationTemplates.length > 0) await insertMany(rationTemplates,rationTemplateModel);
+    if(newCalcProgramsFile) await calcProgramsModel.create(newCalcProgramsFile);
+    if(newLabourCoe) await labourCoesModel.create(newLabourCoe);
+
+
+}
+
+
+function setRationSubList(datas,newProjectID,billIDMap,rationIDMap,projectGLJIDMap) {
+    let arrs = [];
+    for(let d of datas){
+        delete d._id;
+        d = getCopyRationSubData(d,newProjectID,billIDMap,rationIDMap,projectGLJIDMap);
+        arrs.push(d);
+    }
+    return arrs;
+}
+
+async function handleMainProjectDatas(mainData,updateData,userID) {
+    let mainProjectID = -1;
+    let projectIDMap = {},feeRateFileIDMap={},unitPriceFileIDMap={},labourCoeFileIDMap={},calcProgramFileIDMap={};
+    let tasks = [];
+    //生成新的projectID
+    for(let p of mainData.projects){
+        let newProjectID = await getCounterID("projects");
+        projectIDMap[p.ID] = newProjectID;
+        if(p.projType == "Project") mainProjectID =  newProjectID;
+        if(p.projType == "Tender"){
+            if(p.property.calcProgramFile) calcProgramFileIDMap[p.property.calcProgramFile.ID] = uuidV1();//新的计算程序文件ID
+            if(p.property.labourCoeFile) labourCoeFileIDMap[p.property.labourCoeFile.ID] = uuidV1();//新的人工调整系数文件ID
+            if(p.property.feeFile) feeRateFileIDMap[p.property.feeFile.id] = uuidV1();//新的费率文件ID
+            if(p.property.unitPriceFile) unitPriceFileIDMap[p.property.unitPriceFile.id] = await getCounterID("unit_price_file");//新的单价文件ID
+        }
+    }
+    if(mainProjectID == -1) throw new Error("文件里面没包含建设项目信息!");
+
+    //处理项目信息  ----- 费率文件,单价文件ID信息要重新生成----to do
+    for(let p of mainData.projects){
+        delete p._id;
+        delete p.__v;
+        p.ID = projectIDMap[p.ID];
+        if(p.ID == mainProjectID){//对于建设项目,要父和下一节点ID要使用前端传入的位置ID
+            p.ParentID = updateData.self.ParentID;
+            p.NextSiblingID = updateData.self.NextSiblingID;
+            if(updateData.update){//树节构中的上一节点的下一节点设置为本建设项目ID;
+                tasks.push({updateOne:{filter : updateData.update.query, update : {NextSiblingID:mainProjectID}}});
+            }
+            //查看是否重名;
+            let temp = await projectModel.findOne({userID:userID,ParentID:p.ParentID,name:p.name});
+            if(temp) p.name = p.name + '(' + moment(Date.now()).format('MM-DD HH:mm:ss') + '导入)';
+        }else {
+            p.ParentID = projectIDMap[p.ParentID];
+            p.NextSiblingID = projectIDMap[p.NextSiblingID];
+        }
+        p.userID =userID;
+        p.shareInfo=[];
+        if(p.projType == "Tender"){
+            if(p.property.calcProgramFile) p.property.calcProgramFile.ID = calcProgramFileIDMap[p.property.calcProgramFile.ID];
+            if(p.property.labourCoeFile) p.property.labourCoeFile.ID = labourCoeFileIDMap[p.property.labourCoeFile.ID];
+            if(p.property.feeFile) p.property.feeFile.id = feeRateFileIDMap[p.property.feeFile.id];
+            if(p.property.unitPriceFile) p.property.unitPriceFile.id = unitPriceFileIDMap[p.property.unitPriceFile.id];
+            p.property.rootProjectID = mainProjectID
+        }
+        tasks.push({insertOne: {document: p}})
+    }
+    //项目树节构数据生成:
+      await projectModel.bulkWrite(tasks);
+
+    //生成所有的费率文件
+    await importFeeRateFiles(mainData,projectIDMap,feeRateFileIDMap,userID);
+
+    //生成所有的单价文件
+    await importUnitPriceFiles(mainData,projectIDMap,unitPriceFileIDMap,userID);
+
+
+    return [projectIDMap,labourCoeFileIDMap,calcProgramFileIDMap]
+}
+
+
+async function importUnitPriceFiles(mainData,projectIDMap,unitPriceFileIDMap,userID) {
+    if(!mainData.files.unitFiles) return;
+    let unitFiles = [],unitPrices =[],mixRatios=[],freights=[],originals=[];
+    for(let f of mainData.files.unitFiles){
+        let file = f.unitFile,prices = f.unitPrices,mixs = f.mixRatios,fres = f.freights,ors = f.originals;
+        //生成单价文件
+        delete file._id;
+        file.id = unitPriceFileIDMap[file.id]?unitPriceFileIDMap[file.id]:await getCounterID("unit_price_file");
+        file.project_id = projectIDMap[file.project_id];
+        file.root_project_id = projectIDMap[file.root_project_id];
+        file.user_id = userID;
+        unitFiles.push(file);
+
+        //生成子数据
+        if(prices) await  setSubList(prices,unitPrices,file.id,unitPriceModel);
+        if(mixs) await setSubList(mixs,mixRatios,file.id,mixRatioModel);
+        if(fres) await setSubList(fres,freights,file.id,freightModel,true);
+        if(ors) await setSubList(ors,originals,file.id,originalModel,true);
+    }
+    if(unitFiles.length > 0) await insertMany(unitFiles,unitPriceFileModel);
+    if(unitPrices.length > 0) await insertMany(unitPrices,unitPriceModel);
+    if(mixRatios.length > 0) await insertMany(mixRatios,mixRatioModel);
+    if(freights.length > 0) await insertMany(freights,freightModel);
+    if(originals.length > 0) await insertMany(originals,originalModel);
+
+    async function setSubList(oList,nList,fileID,model,UUID=false) {
+        for(let o of oList){
+            delete o._id;
+            o.unit_price_file_id = fileID;
+            UUID == true?o.ID = uuidV1():o.id = await getCounterID(model.modelName);
+            nList.push(o)
+        }
+    }
+
+
+}
+
+
+async function importFeeRateFiles(mainData,projectIDMap,feeRateFileIDMap,userID) {
+    let feeRateFiles = [], feeRates = [];
+    if(!mainData.files.feeRateFiles) return;
+    for(let f of mainData.files.feeRateFiles){
+        //生成费率记录
+        let rate = f.feeRate;
+        delete rate._id;
+        rate.ID = uuidV1();
+        feeRates.push(rate);
+
+        //生成费率文件记录
+        let file = f.feeRateFile;
+        delete file._id;
+        file.ID = feeRateFileIDMap[file.ID]?feeRateFileIDMap[file.ID]:uuidV1();
+        file.userID = userID;
+        file.rootProjectID = projectIDMap[file.rootProjectID];
+        file.feeRateID = rate.ID;
+        feeRateFiles.push(file);
+    }
+    if(feeRateFiles.length > 0) await insertMany(feeRateFiles,feeRateFileModel);
+    if(feeRates.length > 0) await insertMany(feeRates,feeRateModel);
 }

+ 43 - 1
public/web/PerfectLoad.js

@@ -83,5 +83,47 @@ jQuery.bootstrapLoading = {
     },
     end: function () {
         $("#loadingPage").remove();
+    },
+    progressStop:true,
+    progressStart:async function(title="导出文件",autoBar = false){
+        if($("#progressModal").length == 0){
+            let phtml =    `<div class="modal fade" id="progressModal" data-backdrop="static">
+                            <div class="modal-dialog" role="document">
+                                <div class="modal-content">
+                                    <div class="modal-header">
+                                         <h5 class="modal-title" id="progress_modal_title">${title}</h5>
+                                    </div>
+                                     <div class="modal-body">
+                                        <!--正在生成-->
+                                        <h5 class="my-3" id="progress_modal_body">正在${title}</h5>
+                                        <div class="progress mb-3">
+                                        <div id="progress_modal_bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" style="width: 10%"></div>
+                                        </div>
+                                     </div>
+                                   </div>
+                                </div>
+                            </div>`;
+            $("body").append(phtml);
+        }else {
+            $("#progress_modal_title").text(title);
+            $("#progress_modal_body").text(`正在${title}`);
+         }
+        $("#progress_modal_bar").css('width','0%');
+        $("#progressModal").modal('show');
+        if(autoBar == true){//假的进度条
+            $.bootstrapLoading.progressStop = false;
+            let width = 0;
+            while ($.bootstrapLoading.progressStop == false){
+                await  setTimeoutSync(null,1000);
+                width += 5;
+                if(width > 90) width -= 50;
+                $("#progress_modal_bar").css('width',`${width}%`);
+            }
+        }
+    },
+    progressEnd:function () {
+        $("#progress_modal_bar").css('width','100%');
+        $.bootstrapLoading.progressStop = true;
+        $("#progressModal").modal('hide');
     }
-}
+};

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

@@ -156,4 +156,9 @@ function setTimeoutSync(handle, time) {
             resolve();
         }, time);
     });
-}
+}
+
+async function progressStart(title,autoProgress = false){
+
+}
+

+ 13 - 34
web/building_saas/pm/html/project-management.html

@@ -646,54 +646,33 @@
     </div>
 </div>
 
-<!--弹出 导出-->
-<div class="modal fade" id="export" data-backdrop="static">
-    <div class="modal-dialog" role="document">
-        <div class="modal-content">
-            <div class="modal-header">
-                <h5 class="modal-title">导出文件</h5>
-              <!--  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                    <span aria-hidden="true">&times;</span>
-                </button>-->
-            </div>
-            <div class="modal-body">
-                <!--正在生成-->
-                <h5 class="my-3">正在生成文件</h5>
-                <div class="progress mb-3">
-                    <div id="export_progress_bar" class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100" style="width: 10%"></div>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
 
-<!--弹出 导出-->
+
+<!--弹出 导入-->
 <div class="modal fade" id="import" data-backdrop="static">
-    <div class="modal-dialog" role="document">
+    <div class="modal-dialog" style="z-index: 800" role="document">
         <div class="modal-content">
             <div class="modal-header">
-                <h5 class="modal-title">导入建设项目</h5><button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                <span aria-hidden="true">&times;</span>
-            </button>
+                <h5 class="modal-title">导入建设项目</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
             </div>
             <div class="modal-body">
-                <form>
-                    <div class="form-group">
-                        <label>请选择ybp格式文件</label>
-                        <input class="form-control-file" type="file" accept=".ybp" name="import_project_data"/>
-                    </div>
-                </form>
+                <div class="custom-file">
+                    <input type="file" class="custom-file-input" name="import_project_data" id="import_project_data" lang="zh" accept=".ybp">
+                    <label class="custom-file-label"  id="import_project_label" style="white-space: nowrap; overflow: hidden;">请选择建设项目文件</label>
+                </div>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-primary" id="confirm-import">确定导入</button>
-                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-primary " disabled id="confirm-import">确定导入</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
             </div>
         </div>
     </div>
 </div>
 
 
-
 <!-- JS. -->
 <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js"></script>
 <script src = "/lib/fileSaver/FileSaver.min.js"></script>

+ 81 - 14
web/building_saas/pm/js/pm_newMain.js

@@ -346,9 +346,9 @@ const projTreeObj = {
                 let selectedItem = projTreeObj.tree.selected;
                 return !(selectedItem && selectedItem.data.projType === projectType.project);
             },
-            visible:function () {
+           /* visible:function () {
                 return false
-            },
+            },*/
             callback: function (key, opt) {
                 //获取当前节点的建设项目ID
                 projTreeObj.exportProject(projTreeObj.tree.selected.data.ID,projTreeObj.tree.selected.data.name);
@@ -359,11 +359,20 @@ const projTreeObj = {
             icon: 'fa-external-link',
             disabled: function () {
                 let selectedItem = projTreeObj.tree.selected;
-                return !(selectedItem && selectedItem.data.projType === projectType.project);
+                if(selectedItem){
+                    if(selectedItem.data.projType === projectType.project) return false;//如果是建设项目,可用
+                    if(selectedItem.data.projType === projectType.folder){//如果是文件夹
+                        if(selectedItem.children){
+                            if(selectedItem.children.length == 0) return false;//如果文件夹没有子项,可用
+                            if(selectedItem.children[0] .projType === projectType.project ) return false;//如果文件夹有子项,并且是建设项目,可用
+                        }
+                    }
+                }
+                return true;
             },
-            visible:function () {
+          /*  visible:function () {
               return false
-            },
+            },*/
             callback: function (key, opt) {
                 //获取当前节点的建设项目ID
                 $("#import").modal('show');
@@ -1474,13 +1483,13 @@ const projTreeObj = {
         this.refreshProjectData(projectID);
     },
      exportProject:async function(projectID,projectName){
-        $("#export_progress_bar").css('width','0%');
-        $("#export").modal('show');
+        $.bootstrapLoading.progressStart();
         let spString = "|----|";
         try {
             let sumString = "";
+            $("#progress_modal_bar").css('width','5%');
             let result = await getProjectInfo({projectID:projectID,type:"main",user_id: userID});
-            $("#export_progress_bar").css('width','10%');
+            $("#progress_modal_bar").css('width','10%');
             let result_arr = result.split(spString);
             sumString = result_arr[0];
             if(result_arr.length == 2){
@@ -1491,20 +1500,19 @@ const projTreeObj = {
                 for(let t of tenders){
                     let tenderString = await getProjectInfo({projectID:t,rootProjectID:projectID,type:"sub",user_id: userID});
                     width += each;
-                    $("#export_progress_bar").css('width',width+'%');
+                    $("#progress_modal_bar").css('width',width+'%');
                     await  setTimeoutSync(null,500);//设置间隔
                     sumString = sumString + spString +tenderString;
-                    console.log(JSON.parse(tenderString));
                 }
 
             }
-            $("#export_progress_bar").css('width','100%');
-            $("#export").modal('hide');
+            $.bootstrapLoading.progressEnd();
           //  console.log(JSON.parse(sumString));
 
             saveProjectFile(sumString);
 
         }catch (e){
+            alert("导出失败!请查看log.");
             console.log(e)
         }
 
@@ -1528,7 +1536,23 @@ const projTreeObj = {
             },1000)
             //$("#export").modal('hide');
         },1000)*/
+    },
+    getImportProjectDate:function () {//导入建设项目时,需要在现有的树节点中插入新的节点,这里是取插入所需的项目数据
+        let selectNode = projTreeObj.tree.selected;
+        let parent = null,next=null;
+        let updateData = {};
+        if(selectNode && selectNode.data.projType == projectType.folder){
+            parent = selectNode;
+            next = selectNode.firstChild();
+        }else if(selectNode &&  selectNode.data.projType == projectType.project){
+            parent = selectNode.parent;
+            next = selectNode.nextSibling;
+            updateData["update"] = {query:{ID:selectNode.id()}}
+        }
+        updateData["self"] ={ParentID:parent.id(),NextSiblingID:next?next.id():-1};
+        return updateData;
     }
+
 };
 
 $(document).ready(function() {
@@ -2093,11 +2117,11 @@ function initProjects(callback) {
  *
  * @return {void}
  */
-function init() {
+function init(refresh = false) {//refresh是刷新页面时才使用的
     billValuation = billValuation.replace(/\n/g, '\\n');
     rationValuation = rationValuation.replace(/\n/g, '\\n');
     //init spread and pmTree
-    socketObject.connect('pm');//socket 连接;
+    if(refresh == false) socketObject.connect('pm');//socket 连接;
     if (isFirst) {
         $('#progress').modal('show');
         let intervalTime = prepareInitialTimer();
@@ -2120,6 +2144,16 @@ function init() {
     engineering = engineeringList !== null && engineeringList !== undefined ? JSON.parse(engineeringList) : [];
 }
 
+function refreshAllPage(){
+    if(gcTreeObj.workBook){
+        gcTreeObj.workBook.destroy();
+        gcTreeObj.workBook = null;
+    }
+    gcTreeObj.tree = null;
+    init(true);
+}
+
+
 /**
  * 新增建设项目
  *
@@ -3575,6 +3609,7 @@ $('#otherProject').change(function(){
     }
 });
 
+
 //分享给...界面确认
 $('#shareToConfirm').click(function () {
     let selected = projTreeObj.tree.selected;
@@ -3596,6 +3631,9 @@ $("#confirm-import").click(function() {
         }
         formData.append('file', file.files[0]);
         formData.append('userID', userID);
+        formData.append("updateData",JSON.stringify(projTreeObj.getImportProjectDate()));
+        $('#import').modal("hide");
+        $.bootstrapLoading.progressStart("导入建设项目",true);
         $.ajax({
             url: '/pm/api/importProject',
             type: 'POST',
@@ -3608,6 +3646,13 @@ $("#confirm-import").click(function() {
                 self.text('上传中...');
             },
             success: function(response){
+                self.text('确定导入');
+                $.bootstrapLoading.progressEnd();
+                if(response.error == 1){
+                    alert(response.msg);
+                }else {
+                    refreshAllPage();
+                }
 
             },
             error: function(){
@@ -3620,6 +3665,28 @@ $("#confirm-import").click(function() {
     }
 });
 
+$("#import_project_data").change(function(){
+    let file = $(this)[0];
+    let projectFile = file.files[0];
+    if(projectFile) {
+        let ybpReg = /ybp$/g;
+        if(projectFile.name && ybpReg.test(projectFile.name)){
+            $('#import_project_label').text(`${projectFile.name}`);
+            $('#confirm-import').removeAttr("disabled");
+        }else {
+            alert("请选择ybp项目文件");
+            $(this).val('');
+            $('#confirm-import').attr("disabled","disabled");
+        }
+    }
+});
+
+//清空导入清单选择文件
+$('#import').on('show.bs.modal', function(){
+    $('#import_project_data').val('');
+    $('.custom-file-label').text(`请选择建设项目文件`);
+});
+
 //设置分享给界面数据
 //@param {Object}selected @return {void}
 function setShareToModal(selected){