Browse Source

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

chenshilong 5 years ago
parent
commit
b0b4cd9ee7

+ 0 - 31
modules/all_models/product.js

@@ -1,31 +0,0 @@
-'use strict';
-
-/**
- *
- *
- * @author Zhong
- * @date 2019/3/21
- * @version
- */
-/*
- * 与产品绑定的信息都可以在此设置
- * */
-const mongoose = require('mongoose');
-const Schema = mongoose.Schema;
-const productSchema = new Schema({
-    name: {
-        type: String,
-        default: '纵横建筑计价'
-    },
-    company: {
-        type: String,
-        default: '珠海纵横创新软件有限公司'
-    },
-    icp: {
-        type: String,
-        default: '粤ICP备14032472号'
-    },
-    version: String
-}, {versionKey: false});
-
-mongoose.model('product', productSchema, 'product');

+ 3 - 0
modules/all_models/system_setting.js

@@ -21,5 +21,8 @@ let modelSchema = {
         project: Number,
         ration:Number
     },
+    company: String, // 软件供应商
+    product: String, // 产品名
+    version: String // 版本号
 };
 mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));

+ 6 - 2
modules/all_models/user.js

@@ -26,10 +26,14 @@ const versionSchema = new Schema({
 });
 
 let upgrade = mongoose.Schema({
-    compilationID:String,//编办ID
+    compilationID:String,// 编办ID
     upgrade_time:Number,
     isUpgrade:Boolean,
-    remark:String//描述:广东办刘飞 2018-06-17 启用/关闭
+    remark:String,// 描述:广东办刘飞 2018-06-17 启用/关闭
+    deadline: {
+        type:String,
+        default: '',
+    },
 }, { _id: false })
 
 const userdList = mongoose.Schema({

+ 4 - 0
modules/import/controllers/import_controller.js

@@ -17,6 +17,10 @@ let controller = {
         let data = req.body;
         return await pm_facade.importChongqingProject(data);
     },
+    copyConstructionProject:async function(req){
+      let data = req.body;
+      return await pm_facade.copyConstructionProject(data);
+    },
     prepareInitialData: async function(req) {
         const data = req.body;
         return await pm_facade.prepareInitialData(data.userID, data.compilationID, data.example);

+ 1 - 0
modules/import/routes/import_route.js

@@ -13,6 +13,7 @@ module.exports = function (app) {
     importRouter.post('/getDataForInterface',importController.action);
     importRouter.post('/loadSEIProjectData',importController.action);
     importRouter.post('/importChongqingProject',importController.action);
+    importRouter.post('/copyConstructionProject',importController.action);
     importRouter.post('/prepareInitialData',importController.action);
     importRouter.get('/test',function (req,res) {
         res.json("hello word");

+ 4 - 1
modules/main/routes/main_route.js

@@ -6,6 +6,7 @@
 import BaseController from "../../common/base/base_controller";
 const projectModel = require("../../pm/models/project_model");
 const pmFacade = require('../../pm/facade/pm_facade');
+const systemSettingModel = require('../../system_setting/model/index');
 let config = require("../../../config/config.js");
 import OptionsDao from '../../options/models/optionsModel';
 import optionSetting from '../../options/models/optionTypes';
@@ -40,6 +41,7 @@ module.exports =function (app) {
                     options = await optionsDao.saveOptions(req.session.sessionUser.id, req.session.sessionCompilation._id, optionSetting);
                 }
                 const markReadProjectIDs = isOpenShareProject ? await pmFacade.markShareItemsRead(projectID, req.session.sessionUser.id) : [];
+                const version = await systemSettingModel.getVersion();
                 res.render('building_saas/main/html/main.html',
                     {
                         userAccount: req.session.userAccount,
@@ -54,7 +56,8 @@ module.exports =function (app) {
                         overWriteUrl:req.session.sessionCompilation.overWriteUrl,
                         fileKind: fileKind,
                         options:JSON.stringify(options),
-                        markReadProjectIDs: JSON.stringify(markReadProjectIDs)
+                        markReadProjectIDs: JSON.stringify(markReadProjectIDs),
+                        version
                     });
             } else {
                 res.redirect('/pm');

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

@@ -873,7 +873,7 @@ module.exports = {
         };
         try {
             data.session = req.session;
-            result = await redirectToImportServer(data, "importChongqingProject", req);
+            result.data = await redirectToImportServer(data, "importChongqingProject", req);
         } catch (err) {
             console.log(err);
             result.error = 1;
@@ -881,6 +881,21 @@ module.exports = {
         }
         res.json(result);
     },
+    copyConstructionProject: async function (req, res) {
+      let data = JSON.parse(req.body.data);
+      let result = {
+          error: 0
+      };
+      try {
+          data.session = req.session;
+          result.data = await redirectToImportServer(data, "copyConstructionProject", req);
+      } catch (err) {
+          console.log(err);
+          result.error = 1;
+          result.message = err.message;
+      }
+      res.json(result);
+    },
     importProcessChecking: async function (req, res) {
         let result = {
             error: 0

+ 42 - 5
modules/pm/facade/pm_facade.js

@@ -52,6 +52,7 @@ module.exports={
     downLoadProjectFile:downLoadProjectFile,
     importChongqingProject:importChongqingProject,
     importProcessChecking:importProcessChecking,
+    copyConstructionProject,
     importInterface,
     isTenderOverrun,
     getWelcomeInfo:getWelcomeInfo
@@ -91,7 +92,6 @@ let compilationModel = mongoose.model('compilation');
 let engineeringModel = mongoose.model('engineering_lib');
 let basicInfoModel = mongoose.model('std_basic_info_lib');
 let projectFeatureModel = mongoose.model('std_project_feature_lib');
-let productModel = mongoose.model('product');
 let stdRationItemModel = mongoose.model('std_ration_lib_ration_items');
 let stdGljItemModel = mongoose.model('std_glj_lib_gljList');
 import BillsTemplateModel from "../models/templates/bills_template_model";
@@ -442,7 +442,7 @@ async function getShareInfoAfterChangePermission(permissionType, receiver, proje
 
 //拷贝例题项目
 //@param {String}userID {Array}projIDs拷贝的例题项目ID(建设项目、文件夹)@return {Boolean}
-async function copyExample(userID, compilation, projIDs){
+async function copyExample(userID, compilation, projIDs,nameMap){
     let allProjs = [],
         IDMapping = {},
         projMapping = {};
@@ -462,6 +462,7 @@ async function copyExample(userID, compilation, projIDs){
         if (i === parentExample.length - 1) {
             data.NextSiblingID = -1;
         }
+        if(nameMap && nameMap[data.ID]) data.name = nameMap[data.ID];
     }
     //获取所有的子项目
     let posterityProjs = await getPosterityProjects(projIDs);
@@ -1656,6 +1657,42 @@ async function isFirst(userId, compilationId) {
     return first;
 }
 
+async function copyConstructionProject(data){
+  let log_data = {
+    key:data.key,
+    content: '正在复制建设项目,请稍候……',
+    userID:data.user_id,
+    compilationID: data.session.sessionCompilation._id,
+    status:"start",
+    create_time:+new Date()
+  };
+
+  await importLogsModel.create(log_data);
+  doCopy(data.user_id,data.session.sessionCompilation._id,data.projectID,data.newName,data.key);
+
+  return "start copy";
+  async function doCopy(user_id,compilationId,projectID,newName,key) {
+      let doc = {status:"finish"};
+      try {
+          let nameMap={};
+          nameMap[projectID] = newName
+          let r = await copyExample(user_id,compilationId,[projectID],nameMap);
+          if(r == false){
+              doc.errorMsg = "复制失败,请检查项目是否存在!";
+              doc.status = "error";
+          }
+      }catch (error){
+          console.log(error);
+          doc.errorMsg = "复制失败,请检查项目是否存在!";
+          doc.status = "error";
+      }finally {
+          await importLogsModel.update({key:key},doc);
+      }
+  }
+
+
+}
+
 async function importChongqingProject(data) {
 
     let log_data = {
@@ -1872,9 +1909,9 @@ async function getProjectByGranularity(tenderID, granularity, summaryField, user
     //获取汇总信息
     constructionProject.summaryInfo = await getSummaryInfo([constructionProject.ID], summaryField);
     //获取编制软件信息: 软件公司;软件名;版本号;授权信息; base64
-    let product = await productModel.findOne({});
-    let company = product.company || '珠海纵横创新软件有限公司',
-        version = product.version || '';
+    const systemSetting = await systemSettingModel.findOne({});
+    let company = systemSetting.company || '珠海纵横创新软件有限公司',
+        version = systemSetting.version || '';
     constructionProject.softInfo = `${company};${versionName};${version};${userID}`;
     return constructionProject;
 }

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

@@ -66,6 +66,7 @@ module.exports = function (app) {
     pmRouter.post('/exportProject', pmController.exportProject);
     pmRouter.post('/importProject', pmController.importProject);
     pmRouter.post('/importChongqingProject', pmController.importChongqingProject);
+    pmRouter.post('/copyConstructionProject',systemMiddleware.tenderNumberChecking,pmController.copyConstructionProject);
     pmRouter.post('/importProcessChecking', pmController.importProcessChecking);
     pmRouter.post('/getBasicInfo', pmController.getBasicInfo);
     pmRouter.post('/getProjectFeature', pmController.getProjectFeature);

+ 11 - 0
modules/system_setting/model/index.js

@@ -0,0 +1,11 @@
+module.exports = {
+    getVersion,
+};
+
+const mongoose = require('mongoose');
+const sysModel = mongoose.model('system_setting');
+
+async function getVersion() {
+    const data = await sysModel.findOne({}, '-_id version').lean();
+    return data && data.version || '';
+}

+ 14 - 4
modules/users/controllers/cld_controller.js

@@ -12,6 +12,7 @@ import CLDModel from "../models/cld_model";
 import UserModel from "../models/user_model"
 import CompilationModel from "../models/compilation_model";
 let online_facade = require('../facade/online_facade')
+const SMS = require('../models/sms');
 
 class CLDController {
 
@@ -106,6 +107,9 @@ class CLDController {
     async setUsersUpgrade(request, response) {
         let ssoID = request.body.ssoId;
         let compilationID = request.body.cid;
+        let deadline = request.body.deadline || '';
+        let status = parseInt(request.body.status);
+        let smssend = parseInt(request.body.smssend);
         try {
 
             let userModel = new UserModel();
@@ -114,7 +118,7 @@ class CLDController {
 
             let compilationModel = new CompilationModel();
 
-            let compilationData = compilationModel.getCompilationById(compilationID);
+            let compilationData = await compilationModel.getCompilationById(compilationID);
 
             if (compilationData === null || compilationData === undefined) {
                 throw '不存在该编办或者编办未发布';
@@ -125,12 +129,12 @@ class CLDController {
             let upgradeIndex = upgrade_list.findIndex(function (item) {
                 return item.compilationID === compilationID
             });
-
             let upgradeInfo = {
                 compilationID:compilationID,//编办ID
                 upgrade_time:new Date().getTime(),
-                isUpgrade:true,
-                remark: ''
+                isUpgrade: status !== 2,
+                remark: '',
+                deadline: deadline,
             };
 
             if (upgradeIndex === -1) {
@@ -143,6 +147,12 @@ class CLDController {
             let result = await userModel.updateUser(condition, {upgrade_list: upgrade_list});
 
             if (result) {
+                // 短信发送
+                if (smssend) {
+                    // 发送短信
+                    const Sms = new SMS();
+                    await Sms.sendProductMsg(userData.mobile, status, userData.real_name, compilationData.name, deadline);
+                }
                 response.json({error: 0, msg: 'success'});
             } else {
                 throw '更新失败';

+ 45 - 0
modules/users/models/sms.js

@@ -111,6 +111,51 @@ class SMS {
         }
     }
 
+    async sendProductMsg(mobile, status, name, product, deadline) {
+        try {
+            let templateId = 0;
+            switch (status) {
+                case 1: templateId = 746377;break;// 产品升级通知
+                case 2: templateId = 746376;break;// 产品降级通知
+                case 3: templateId = 746378;break;// 产品延期通知
+            }
+            const formData = {
+                smsUser: this.smsUser,
+                templateId: templateId,
+                msgType: 0,
+                phone: mobile,
+            };
+            formData.vars = '{"%name%": "' + name + '", "%product%": "' + product + '"' + (status !== 2 ? ', "%deadline%": "' + deadline + '"' : '') +'}';
+            const signature = await this.getSignature(this.sortDict(formData), this.smskey);
+            formData.signature = signature;
+
+            let postData = {
+                url: this.url,
+                form: formData,
+                encoding: 'utf8'
+            };
+
+            return new Promise(function (resolve, reject) {
+                try {
+                    // 请求接口
+                    Request.post(postData, function (err, postResponse, body) {
+                        if (err) {
+                            throw '请求错误';
+                        }
+                        if (postResponse.statusCode !== 200) {
+                            throw '短信发送失败!';
+                        }
+                        resolve(body);
+                    });
+                } catch (error) {
+                    reject([]);
+                }
+            });
+        } catch (error) {
+            console.log(error);
+        }
+    }
+
     md5(data) {
         var str = data;
         return crypto.createHash("md5").update(str).digest("hex");

+ 1 - 1
modules/users/models/user_model.js

@@ -386,7 +386,7 @@ class UserModel extends BaseModel {
     /**
      * 从session中判断用户是否是免费版
      * @param {String} sessionVersion
-     * @return {Boolean} 
+     * @return {Boolean}
      */
     isFreeFromSession(sessionVersion) {
         if (!sessionVersion) {

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

@@ -333,7 +333,7 @@ var sheetCommonObj = {
 
         for (var col = 0; col < setting.header.length; col++) {
             //var cell = sheet.getCell(row, col, GC.Spread.Sheets.SheetArea.viewport);
-            var val = data[row][setting.header[col].dataCode];
+            var val = _.get(data[row],setting.header[col].dataCode);
             let style = null;
             if(data[row].foreColor && data[row].styleCol == col){
                 style = {foreColor: data[row].foreColor};

+ 7 - 3
web/building_saas/glj/html/project_glj.html

@@ -80,12 +80,16 @@
             <div class="resize-y" id="projectGljResize"></div>
             <div class="bottom-content" id="projectGljBottom">
                 <ul class="nav nav-tabs" role="tablist">
+                  <li class="nav-item">
+                    <a class="nav-link active show" id="mixRatio-nav" data-toggle="tab" href="#ph_div" role="tab" aria-selected="false">组成物计算</a>
+                  </li>
+                  <li class="nav-item">
+                    <a class="nav-link " id="ration-nav" data-toggle="tab" href="#ph_div" role="tab" aria-selected="true">相关定额</a>
+                  </li>
                   <!--  <li class="nav-item">
                         <a class="nav-link active" data-toggle="tab" data-name="ration_sheet" id="ration_link" href="#glj_de_div" role="tab">相关定额</a>
                     </li>-->
-                   <!-- <li class="nav-item">
-                        <a class="nav-link active" data-toggle="tab" data-name="mix_ratio_sheet" id="mix_ratio_link" href="#ph_div" role="tab">组成物</a> 配合比、机械单价表合并
-                    </li>-->
+                   
                    <!-- <li class="nav-item">
                         <a class="nav-link" data-toggle="tab" data-name="machine_sheet" id="machine_ratio_link" href="#ph_div" role="tab">机械单价</a>
                     </li>-->

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

@@ -46,6 +46,7 @@
         console.log(projectCooperate);
         const G_SHOW_BLOCK_LIB = true;
         const markReadProjectIDs = JSON.parse('<%- markReadProjectIDs %>');
+        const VERSION = '<%- version %>';
 //        const G_SHOW_BLOCK_LIB = false;
     </script>
 </head>

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

@@ -24,7 +24,7 @@ $(function () {
         rationLibObj.refreshSpread();
         subObj.initGljSubTab();
         subObj.initQDSubTab();
-        refreshSubSpread();
+        //refreshSubSpread();
     });
 
     $('#tab_report').on('shown.bs.tab', function(e){
@@ -80,7 +80,7 @@ function loadMainSize() {//加载造价书页面各高度
     let mainResizeEles = getMainResizeEles();
     SlideResize.loadVerticalHeight(mainResizeEles.eleObj.module, mainResizeEles.eleObj, mainResizeEles.limit, function () {
         refreshSubSpread();
-        zmhs_obj.refresh();
+        //zmhs_obj.refresh();
         $("#tzCharacterText").height($("#tzSubDiv").height()-30);
     });
 }

+ 14 - 4
web/building_saas/main/js/models/calc_base.js

@@ -1540,9 +1540,17 @@ let cbCalctor = {
         }
         return 0;
     },
-    //计算
-    exec: function () {
-
+    tenderRef: function (fExp) {
+        let ID = cbParser.getUID([fExp]);
+        if(ID.length === 1){
+            let node = cbTools.getNodeByID(ID[0]);
+            return cbTools.isDef(node) &&
+                    cbTools.isDef(node.data.feesIndex) &&
+                    cbTools.isDef(node.data.feesIndex.common) &&
+                    cbTools.isDef(node.data.feesIndex.common.tenderTotalFee) ?
+                    node.data.feesIndex.common.tenderTotalFee : 0;
+        }
+        return 0;
     }
 };
 
@@ -1602,7 +1610,9 @@ let calcBase = {
                 throw '基数计算结果不为数值';
             }
             //调价
-            let tenderCalcExp = calcExp.replace(new RegExp('base', 'g'), 'tenderBase');
+            let tenderCalcExp = calcExp
+                .replace(new RegExp('base', 'g'), 'tenderBase')
+                .replace(new RegExp('ref', 'g'), 'tenderRef');
             let tenderCalcBaseValue = eval(tenderCalcExp);
             if(!cbTools.isNum(tenderCalcBaseValue)){
                 throw '调价基数计算结果不为数值';

+ 80 - 15
web/building_saas/main/js/views/project_glj_view.js

@@ -13,6 +13,19 @@ let projectGljObject={
     materialTreeSheet:null,
     projectGljSheetData:[],
     mixRatioSetting:{},
+    relatedRationSetting:{
+      header:[
+        {headerName: "编码", headerWidth: 100, dataCode: "code", dataType: "String"},
+        {headerName: "名称", headerWidth: 180, dataCode: "name", dataType: "String"},
+        {headerName: "单位", headerWidth: 50, dataCode: "unit", dataType: "String",hAlign: "center"},
+        {headerName: "工程量", headerWidth: 65, dataCode: "quantity", dataType: "Number", hAlign: "right",decimalField: "ration.quantity"},
+        {headerName: "单价", headerWidth: 65, dataCode: "feesIndex.common.unitFee", dataType: "Number", hAlign: "right",decimalField: "ration.unitPrice"}
+    ],
+    view: {
+        lockColumns: [0,1,2,3,4]//,
+        //colHeaderHeight:30
+      }
+    },
     materialTreeSetting:{
         "emptyRows":0,
         "headRows":1,
@@ -94,12 +107,14 @@ let projectGljObject={
         }
     },
     initMixRatioSpread:function () {
-        this.mixRatioSpread = SheetDataHelper.createNewSpread($("#mix_ratio_sheet")[0]);
+        this.mixRatioSpread = SheetDataHelper.createNewSpread($("#mix_ratio_sheet")[0],2);
         sheetCommonObj.spreadDefaultStyle(this.mixRatioSpread);
         this.mixRatioSheet = this.mixRatioSpread .getSheet(0);
         this.initSheet(this.mixRatioSheet,this.mixRatioSetting);
         this.mixRatioSheet.name('mixRatioSheet');
         this.mixRatioSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMixRatioRangeChange);
+        this.initRelatedRationSheet();
+
         if(projectReadOnly){
             if(this.mixRatioSetting.view.lockColumns){
                 this.mixRatioSetting.view.lockColumns = null;
@@ -107,6 +122,13 @@ let projectGljObject={
             disableSpread(this.mixRatioSpread);
         }
     },
+    initRelatedRationSheet:function(){
+      this.relatedRationSheet = this.mixRatioSpread.getSheet(1); 
+      sheetCommonObj.initSheet(this.relatedRationSheet, this.relatedRationSetting, 30);
+      this.relatedRationSheet.name('relatedRation');
+      this.relatedRationSheet.bind(GC.Spread.Sheets.Events.CellDoubleClick, this.onRelatedRationDoubleClick);
+      //this.mixRatioSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMixRatioRangeChange);
+    },
     initMaterialTreeSheet:function () {
         this.materialTreeSheet = this.projectGljSpread.getSheet(1);
         this.materialTreeSetting = this.createMaterialTreeSheetSetting();
@@ -268,6 +290,8 @@ let projectGljObject={
     },
     showMixRatioData:function () {
         let me = this,gljId = null,gljType = null;
+        if(!$('#mixRatio-nav').hasClass('active')) return;
+        me.mixRatioSpread.setActiveSheetIndex(0);
         if(!me.projectGljSpread) return;
         let sheet = me.projectGljSpread.getActiveSheet();
         let oldSel = me.mixRatioSheet.getSelections()[0];
@@ -303,6 +327,28 @@ let projectGljObject={
           me.mixRatioSheet.setSelection(oldSel.row==-1?0:oldSel.row,oldSel.col,oldSel.rowCount,oldSel.colCount);
         })
     },
+    showRelatedRationDatas:function(){
+      let me = this;
+      if(!$('#ration-nav').hasClass('active')) return;
+      me.mixRatioSpread.setActiveSheetIndex(1);
+      let projectGLJData = me.getProjectGLJSelected();
+      let rationIDMap = {};
+      let rations = [];
+      if(projectGLJData){
+         for(let rg of projectObj.project.ration_glj.datas){
+            if(rg.projectGLJID == projectGLJData.id) rationIDMap[rg.rationID] = true;
+         } 
+         for(let r of projectObj.project.Ration.datas){
+            if(rationIDMap[r.ID] || (r.type == rationType.gljRation && r.projectGLJID== projectGLJData.id)){
+              rations.push(r);
+            } 
+         } 
+      }
+      this.relatedRationSheetData = rations;
+      sheetCommonObj.showData(me.relatedRationSheet, me.relatedRationSetting,rations);
+      me.relatedRationSheet.setRowCount(rations.length);
+    },
+
     getMixRatioSheetData:function (glj) {
         let data ={
             id:glj.id,
@@ -374,6 +420,12 @@ let projectGljObject={
         me.showMixRatioData();
         me.materialTreeSheet.repaint();
     },
+    onRelatedRationDoubleClick:function (sender,args) {
+      let me = projectGljObject;
+      let record = me.relatedRationSheetData[args.row];
+      $("#tab_zaojiashu").click();
+      locateObject.locateNode(record.ID);
+    },
     onProjectGljSelectionChange:function (sender, args) {
         let me = projectGljObject;
         let newSel = args.newSelections[0];
@@ -405,6 +457,7 @@ let projectGljObject={
         sel.rowCount = 1;
         sel.colCount = 1;
         me.showMixRatioData();
+        me.showRelatedRationDatas();
     },
     rightClickCallback:function (row) {
         let me = projectGljObject;
@@ -678,6 +731,7 @@ let projectGljObject={
         }else {
             me.showProjectGljData();
             me.showMixRatioData(); 
+            me.showRelatedRationDatas();
         }
     },
     createMaterialTree:function (gljList) {
@@ -871,6 +925,7 @@ let projectGljObject={
             me.projectGljSheetData.splice(row,1);
             me.projectGljSheet.deleteRows(row,1);
             me.showMixRatioData();
+            me.showRelatedRationDatas();
         }
         //me.projectGljSheetData[row] = me.getSheetDataByGLJ(glj);
     },
@@ -1105,20 +1160,20 @@ let projectGljObject={
         return sheetCommonObj.checkData(col,setting, value);
     },
     getProjectGLJSelected:function () {
-        let me = projectGljObject;
-        let sheet = me.projectGljSpread.getActiveSheet();
-        let selectedProjectGLJ = null;
-        if(sheet.name() == 'projectGljSheet'){//projectGljSheet/materialSheet 工料机汇总和三材汇总表
-            let sel = me.projectGljSheet.getSelections()[0];
-            if(sel.row != -1 && me.projectGljSheetData.length>sel.row){
-                selectedProjectGLJ = me.projectGljSheetData[sel.row]
-            }
-        }else if(sheet.name() == 'materialTreeSheet' ){
-            if(me.materialTree.selected){
-                selectedProjectGLJ = me.materialTree.selected.data;
-            }
-        }
-        return selectedProjectGLJ;
+      let me = this,data = null;
+      let sheet = me.projectGljSpread.getActiveSheet();
+      if(sheet.name() == 'projectGljSheet'){//projectGljSheet/materialSheet 工料机汇总和三材汇总表
+          let sel = me.projectGljSheet.getSelections()[0];
+          let srow = sel.row == -1||sel.row == ""?0:sel.row;
+          if(me.projectGljSheetData.length>srow){
+              data = me.projectGljSheetData[srow];
+          }
+      }else if(sheet.name() == 'materialTreeSheet'){
+          if(this.materialTree.selected){
+              data = this.materialTree.selected.data;
+          }
+      }
+      return data;
     },
     initRightClick : function() {
         let activeSheet = this.mixRatioSheet;
@@ -1544,6 +1599,16 @@ $(function () {
         me.refreshViewsData();
         loadProjectGljSize();
     });
+
+    $("#mixRatio-nav").on('shown.bs.tab', function () {
+      projectGljObject.mixRatioSpread.refresh();
+      projectGljObject.showMixRatioData();
+  });
+
+    $("#ration-nav").on('shown.bs.tab', function () {
+      projectGljObject.mixRatioSpread.refresh();
+      projectGljObject.showRelatedRationDatas();
+    });
 });
 
 

+ 0 - 1
web/building_saas/main/js/views/zmhs_view.js

@@ -259,7 +259,6 @@ let zmhs_obj = {
     refresh:function () {
         $('#coeSpread').is(':visible')&&this.coeSpread?this.coeSpread.refresh():'';
         $('#coeSpread').is(':visible')&&this.coeSpread?this.showDatas():'';//这里combobox下拉框要重新加载一下
-        $('#coeSpread').is(':visible')&&this.coeSpread?this.coeSpread.refresh():'';
         $('#cusSpread').is(':visible')&&this.cusSpread?this.cusSpread.refresh():'';
         $('#assSpread').is(':visible')&&this.assSpread?this.assSpread.refresh():'';
     },

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

@@ -424,7 +424,7 @@ const pmShare = (function () {
             let node = tree.items[options.row];
             // Draw Text
             GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
-            if (node && node.data.projType === projectType.tender) {
+            if (node && (node.data.projType === projectType.tender||node.data.projType === projectType.project)) {
                 let text = options.sheet.getText(options.row, options.col);
                 let acStyle = options.sheet.getActualStyle(options.row, options.col),
                     zoom = options.sheet.zoom();
@@ -745,6 +745,7 @@ const pmShare = (function () {
         //data.allowCopy与shareInfo里allowCopy的区别:
         //data.allowCopy为该单位实际的权限(跟着最新的分享信息走,可能随着父项)
         for (let data of datas) {
+            if(data.projType == projectType.project) data.allowCopy = isAllowCopy(userID, data); //20200715 专业版要求能复制建设项目
             if (data.projType === projectType.tender) {
                 data.allowCopy = isAllowCopy(userID, data);
                 data.allowCooperate = isAllowCoop(userID, data);
@@ -796,12 +797,27 @@ const pmShare = (function () {
                     icon: 'fa-copy',
                     disabled: function () {
                         let selected = tree.selected;
-                        return !(selected && selected.data.allowCopy);
+                        return !(selected && selected.data.allowCopy && selected.data.projType === projectType.tender);
                     },
                     callback: function (key, opt) {
                         $('#copyShare').modal('show');
                     }
                 },
+                "copyProject": {
+                  name: "拷贝建设项目",
+                  icon: 'fa-copy',
+                  disabled: function () {
+                      let selected = tree.selected;
+                      return !(selected && selected.data.allowCopy && selected.data.projType === projectType.project);
+                  },
+                  callback: function (key, opt) {
+                      if($(".p-title").text().includes('免费')){
+                        hintBox.versionBox('此功能仅在专业版中提供,免费公用版可选择单个分段进行拷贝');
+                        return;
+                      }
+                      copyContructionProject(tree.selected);
+                  }
+                },
                 "cancel": {
                     name: "清除",
                     icon: 'fa-remove',
@@ -943,6 +959,38 @@ const pmShare = (function () {
         }
 
     }
+
+    //拷贝分享的建设项目
+    //@param {Object}selected 
+    async function copyContructionProject(selected){
+      try {
+        let newName = getCopyName(selected);
+        //获取单项工程的单位工程
+        let projectQuery = {$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], userID: userID,projType: "Project"};
+        const rstData = await ajaxPost('/pm/api/getProjectsByQuery', {user_id: userID, query: projectQuery, options: '-_id -property'}, false, 10000);
+        for(let project of rstData){
+            if(project.name === newName){
+                alert("已存在此建设项目");
+                return;
+            }
+        }
+        let tenderCount = 0;
+        if(selected.children) {
+          for(let c of selected.children){
+            if(c.children) tenderCount += c.children.length;
+          }
+        }
+        let key = uuid.v1();
+        $.bootstrapLoading.progressStart('拷贝建设项目', true);
+        $("#progress_modal_body").text('正在拷贝建设项目,请稍候……');
+        await ajaxPost('/pm/api/copyConstructionProject', {user_id: userID, tenderCount: tenderCount,key:key,projectID:selected.data.actualTreeInfo.ID,newName:newName});
+        importProcessChecking(key, null, projTreeObj.emitTreeChange);
+      } catch (error) {
+        console.log(error);
+      }
+    }
+
+
     //获取拷贝后的名称
     //@param {Object}node @return {String}
     function getCopyName(node) {

+ 19 - 4
web/building_saas/report/js/rpt_main.js

@@ -564,10 +564,11 @@ let rptControlObj = {
                         // $("#ini_PDF_cover").remove();
                     }
                     let pageSize = rptControlObj.getCurrentPageSize();
-                    for (let idx = 0; idx < result.length; idx++) {
-                        let pageData = result[idx];
-                        JpcJsPDFHelper.outputAsPdf(pageData, pageSize, rpt_names[idx]);
-                    }
+                    downloadPDFReport(result, pageSize, rpt_names);
+                    // for (let idx = 0; idx < result.length; idx++) {
+                    //     let pageData = result[idx];
+                    //     JpcJsPDFHelper.outputAsPdf(pageData, pageSize, rpt_names[idx]);
+                    // }
                 },
                 function(failRst){
                     $.bootstrapLoading.end();
@@ -700,6 +701,20 @@ let rptControlObj = {
     }
 };
 
+function downloadPDFReport(pageDataArr, pageSize, rpt_names) {
+    rptControlObj.currentDownloadIdx = 0;
+    const private_download = function() {
+        if (rptControlObj.currentDownloadIdx < pageDataArr.length) {
+            let pageData = pageDataArr[rptControlObj.currentDownloadIdx];
+            let rptName = rpt_names[rptControlObj.currentDownloadIdx];
+            rptControlObj.currentDownloadIdx++;
+            JpcJsPDFHelper.outputAsPdf(pageData, pageSize, rptName);
+            if (rptControlObj.currentDownloadIdx < pageDataArr.length) setTimeout(private_download, 1000);
+        }
+    }
+    private_download();
+}
+
 function downloadReport(urls) {
     //考虑到多个报表下载,一些浏览器(如chrome)不允许一下子下载多个文件,得缓缓处理,统一在这处理
     rptControlObj.currentDownloadUrl = null;