Explorar el Código

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

Conflicts:
	web/building_saas/css/custom.css
zhangweicheng hace 5 años
padre
commit
7dae6178ce
Se han modificado 37 ficheros con 1091 adiciones y 283 borrados
  1. 2 0
      modules/all_models/material_calc.js
  2. 2 0
      modules/all_models/unit_price.js
  3. 4 1
      modules/all_models/unit_price_file.js
  4. 28 19
      modules/complementary_glj_lib/models/gljModel.js
  5. 1 1
      modules/glj/models/unit_price_model.js
  6. 1 1
      modules/main/controllers/project_controller.js
  7. 2 2
      modules/main/models/project.js
  8. 9 1
      modules/pm/controllers/pm_controller.js
  9. 44 3
      modules/pm/facade/pm_facade.js
  10. 53 1
      modules/ration_glj/controllers/ration_glj_controller.js
  11. 64 0
      modules/ration_glj/facade/ration_glj_facade.js
  12. 1 1
      modules/ration_glj/routes/ration_glj_route.js
  13. 32 23
      modules/reports/controllers/rpt_controller.js
  14. 50 0
      modules/unit_price_file/controllers/unit_price_controller.js
  15. 14 0
      modules/unit_price_file/routes/unit_price_router.js
  16. 9 1
      public/common_constants.js
  17. 6 8
      public/web/gljUtil.js
  18. 6 5
      public/web/sheet/sheet_common.js
  19. 10 2
      web/building_saas/complementary_ration_lib/html/dinge.html
  20. 67 84
      web/building_saas/complementary_ration_lib/js/gljSelect.js
  21. 1 0
      web/building_saas/complementary_ration_lib/js/init.js
  22. 1 6
      web/building_saas/complementary_ration_lib/js/ration_glj.js
  23. 0 2
      web/building_saas/complementary_ration_lib/js/section_tree.js
  24. 4 0
      web/building_saas/css/custom.css
  25. 4 0
      web/building_saas/css/main.css
  26. 1 0
      web/building_saas/glj/html/project_glj.html
  27. 5 3
      web/building_saas/main/html/main.html
  28. 27 8
      web/building_saas/main/js/models/project_glj.js
  29. 3 3
      web/building_saas/main/js/models/ration_glj.js
  30. 13 76
      web/building_saas/main/js/views/glj_view.js
  31. 113 18
      web/building_saas/main/js/views/glj_view_contextMenu.js
  32. 8 5
      web/building_saas/main/js/views/project_glj_view.js
  33. 18 8
      web/building_saas/main/js/views/project_info.js
  34. 169 0
      web/building_saas/unit_price_file/index.html
  35. 293 0
      web/building_saas/unit_price_file/index.js
  36. 25 0
      web/common/components/share/index.js
  37. 1 1
      web/common/html/header.html

+ 2 - 0
modules/all_models/material_calc.js

@@ -81,6 +81,7 @@ let freightSchema = {
     loadingTimes:String,//装卸次数
     otherFee:String,//其它费用
     freightIncreaseRate:String,//运价增加率
+    heightFee:String,//高原增加费
     weightCoe:String,//加权系数
     rations:[ration_schema],
     ration_gljs:[ration_glj],
@@ -97,6 +98,7 @@ let originalSchema = {
     supplyLocation:String,//供应地点
     supplyPrice:String,//供应价
     coe:String,//加权系数
+    heightFee:String,//高原增加费
     rations:[ration_schema],
     ration_gljs:[ration_glj]
 };

+ 2 - 0
modules/all_models/unit_price.js

@@ -53,7 +53,9 @@ let modelSchema = {
     },
     supplyLocation:String,//供应地点
     originalPrice:String,//原价
+    priceHeightFee:String,//自采高原增加费
     unitFreight:String,//单价运费
+    freightHeightFee:String,//自办运输高原增加费
     totalLoadingTimes:String,//装卸总次数
     offSiteTransportLoss:String,//场外运输损耗
     purchaseStorage:String,//采购及保管费

+ 4 - 1
modules/all_models/unit_price_file.js

@@ -11,7 +11,10 @@ let Schema = mongoose.Schema;
 let collectionName = 'unit_price_file';
 let modelSchema = {
     // 自增id
-    id: Number,
+    id: {
+      type: Number,
+      index: true
+    },
     // 标段id
     project_id: {
         type: Number,

+ 28 - 19
modules/complementary_glj_lib/models/gljModel.js

@@ -51,29 +51,34 @@ class GljDao {
     }
 
     //获得用户的补充工料机和用户当前所在编办的标准工料机
-    async getGljItems (stdGljLibId, userId, compilationId, projection, callback){
+    async getGljItems(stdGljLibId, userId, compilationId, projection, callback) {
         let me = this;
-        let rst = {stdGljs: [], complementaryGljs: []};
+        let rst = { stdGljs: [], complementaryGljs: [] };
         //批量获取异步
         async.parallel([
-           async function (cb) {
-               try{
-                   let stdGljs = await stdGljModel.find({repositoryId: stdGljLibId}, projection).lean();
-                   me.sortToNumber(stdGljs);
-                   rst.stdGljs = stdGljs;
-                   cb(null);
-               }
-               catch (err){
-                   cb(err);
-               }
+            async function (cb) {
+                try {
+                    let stdGljs = stdGljLibId ? await stdGljModel.find({ repositoryId: stdGljLibId }, projection).lean() : [];
+                    me.sortToNumber(stdGljs);
+                    rst.stdGljs = stdGljs;
+                    cb(null);
+                }
+                catch (err) {
+                    cb(err);
+                }
 
             },
             function (cb) {
-                complementaryGljModel.find({userId: userId, compilationId: compilationId}, '-_id', {lean: true}, function (err, complementaryGljs) {
-                    if(err){
+                if (!userId || !compilationId) {
+                    rst.complementaryGljs = [];
+                    cb(null);
+                    return;
+                }
+                complementaryGljModel.find({ userId: userId, compilationId: compilationId }, '-_id', { lean: true }, function (err, complementaryGljs) {
+                    if (err) {
                         cb(err);
                     }
-                    else{
+                    else {
                         me.sortToNumber(complementaryGljs);
                         rst.complementaryGljs = complementaryGljs;
                         cb(null);
@@ -81,10 +86,10 @@ class GljDao {
                 });
             }
         ], function (err) {
-            if(err){
+            if (err) {
                 callback(err, null);
             }
-            else{
+            else {
                 callback(0, rst);
             }
         })
@@ -313,8 +318,12 @@ class GljDao {
 
     async getMixedTree(gljLibId, userId, compilationId){
         let rst = {std: [], comple: []};
-        rst.std = await gljClassModel.find({repositoryId: gljLibId}).lean();
-        rst.comple = await compleClassModel.find({userId: userId, compilationId: compilationId}).lean();
+        if (gljLibId) {
+            rst.std = await gljClassModel.find({repositoryId: gljLibId}).lean();
+        }
+        if (userId && compilationId) {
+            rst.comple = await compleClassModel.find({userId: userId, compilationId: compilationId}).lean();
+        }
         return rst;
     }
 }

+ 1 - 1
modules/glj/models/unit_price_model.js

@@ -346,7 +346,7 @@ class UnitPriceModel extends BaseModel {
     }
 
     async updateParentUnitPrice(mixRatio,fieid,project_id,newValueMap,batchUpdate){//batchUpdate 批量更新标记,如果true,只生成task
-        let  decimalObject =await decimal_facade.getProjectDecimal(project_id);
+        let  decimalObject =project_id?await decimal_facade.getProjectDecimal(project_id):null;
         let quantity_decimal = (decimalObject&&decimalObject.glj&&decimalObject.glj.quantity)?decimalObject.glj.quantity:3;
         let price_decimal = (decimalObject&&decimalObject.glj&&decimalObject.glj.unitPrice)?decimalObject.glj.unitPrice:2;
         //查找该工料机所有组成物

+ 1 - 1
modules/main/controllers/project_controller.js

@@ -46,7 +46,7 @@ module.exports = {
             } else {
                 callback(req, res, err, message, null);
             }
-        });
+        }, req.session.sessionUser.id);
     },
     markUpdateProject:async function (req,res) {
         let result={

+ 2 - 2
modules/main/models/project.js

@@ -96,7 +96,7 @@ Project.prototype.save = function(datas, callback){
     me.datas = [];
 };
 
-Project.prototype.getData = function(projectID, callback){
+Project.prototype.getData = function(projectID, callback, userID){
     var functions = [];
     var itemName;
     let firstTime = +new Date();
@@ -105,7 +105,7 @@ Project.prototype.getData = function(projectID, callback){
             return function (cb) {
                 moduleMap[itemName].getData(projectID, function(err, moduleName, data){
                     cb(err, {moduleName: moduleName, data: data})
-                })
+                }, userID)
             }
         })(itemName))
     }

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

@@ -201,7 +201,7 @@ module.exports = {
         });
     },
     //project getData接口
-    getData: function(projectID, callback) {
+    getData: function(projectID, callback, userID) {
         projectModel.findOne({$or: [{deleteInfo: null}, {'deleteInfo.deleted': false}], ID: projectID}, '-_id').then(async function (project) {
             if (!project) {
                 callback('', consts.projectConst.PROJECT_INFO, {});
@@ -229,6 +229,14 @@ module.exports = {
             //获取单位工程完整目录结构
             let fullPath = await pm_facade.getFullPath(projectID);
             projInfo.fullPath = fullPath;
+            // 获取分享的tip
+            projInfo.shareTip = await pm_facade.getShareTip(projectID, 2);
+            // 获取分享状态
+            if (typeof userID === 'string') {
+                projInfo.shareState = await pm_facade.getShareState(projectID, userID);
+            }
+            // 获取项目所属用户
+            projInfo.owner = await userModel.findOne({_id: mongoose.Types.ObjectId(project.userID)}, 'real_name');
             callback('', consts.projectConst.PROJECT_INFO, project);
         }, function (err) {
             callback(err, consts.projectConst.PROJECT_INFO, {});

+ 44 - 3
modules/pm/facade/pm_facade.js

@@ -17,6 +17,8 @@ module.exports={
     getShareInfoMap,
     getRecentShareList,
     getProjectShareList,
+    getShareTip,
+    getShareState,
     moveProject:moveProject,
     accessToCopyProject,
     copyProject:copyProject,
@@ -244,26 +246,65 @@ async function getRecentShareList(userID, count) {
 }
 
 // 获取某项目的分享记录
-async function getProjectShareList(projectID) {
-    const sharedList = await shareListModel.find({ projectID }).lean();
+async function getProjectShareList(projectID, limit = null) {
+    const sharedList = limit 
+        ? await shareListModel.find({ projectID }).lean().sort({ shareDate: -1 }).limit(limit)
+        : await shareListModel.find({ projectID }).lean().sort({ shareDate: -1 });
     const userIDs = [];
     const userMap = {};
-    sharedList.forEach(item => {
+    sharedList.forEach((item, index) => {
         userIDs.push(item.receiver);
         userMap[item.receiver] = item;
+        userMap[item.receiver].index = index;
     });
     const userObjectIDs = userIDs.map(userID => mongoose.Types.ObjectId(userID));
     const users = await userModel.find({_id: {$in: userObjectIDs}}, 'real_name mobile company').lean();
     users.forEach(user => {
         const matched = userMap[user._id];
         if (matched) {
+            user.index = matched.index;
             user.allowCopy = matched.allowCopy;
             user.allowCooperate = matched.allowCooperate;
         }
     });
+    users.sort((a, b) => a.index - b.index);
     return users;
 }
 
+// 获取分享的提示(造价书分享按钮tooltip使用)
+async function getShareTip(projectID, limit) {
+    const task = [
+        getProjectShareList(projectID, limit),
+        shareListModel.count({ projectID })
+    ];
+    const [users, count] = await Promise.all(task);
+    return users.reduce((acc, user, index) => {
+        if (index === 0) {
+            acc += '已分享给';
+            acc += user.real_name;
+        } else {
+            acc += ` ${user.real_name}`;
+        }
+        if (index === users.length - 1 && count > limit) {
+            acc += `等${count}人`;
+        }
+        return acc;
+    }, '');
+}
+
+// 获取项目的分享状态
+// 分享项目的拷贝和编辑性,需要参考父项
+// 以项目链上最新更新的分享数据为准
+async function getShareState(projectID, receiver) {
+    const projectIDs = await getUpChainIDs(projectID);
+    const shareList = await shareListModel.find({ projectID: { $in: projectIDs }, receiver }).lean();
+    shareList.sort((a, b) => Date.parse(b.updateDate) - Date.parse(a.updateDate));
+    return {
+        allowCopy: shareList[0] && shareList[0].allowCopy || false,
+        allowCooperate: shareList[0] && shareList[0].allowCooperate || false
+    };
+}
+
 //拷贝例题项目
 //@param {String}userID {Array}projIDs拷贝的例题项目ID(建设项目、文件夹)@return {Boolean}
 async function copyExample(userID, compilation, projIDs){

+ 53 - 1
modules/ration_glj/controllers/ration_glj_controller.js

@@ -5,6 +5,7 @@ let mongoose = require("mongoose")
 let ration_glj_facade = require('../facade/ration_glj_facade')
 import EngineeringLibModel from "../../users/models/engineering_lib_model";
 let logger = require("../../../logs/log_helper").logger;
+const { COMPLEMENTARY_LIB, COMPILATION } = require ('../../../public/common_constants');
 
 module.exports={
     createRationGLJ:createRationGLJ,
@@ -64,7 +65,33 @@ async function getGLJData(req, res) {
         error:0
     }
     try {
-        let info = await ration_glj_facade.getLibInfo(req);
+        let libData = null;
+        let { engineerID, gljLibId, isInitial } = req.params;
+        if (gljLibId !== COMPLEMENTARY_LIB) {
+            gljLibId = +gljLibId;
+        }
+        isInitial = JSON.parse(isInitial);
+        if (!gljLibId || isInitial) { // 替换人材机的话,可能存在gljLibID,但是是初始化的操作
+            console.log(COMPILATION);
+            libData = engineerID === COMPILATION 
+            ? await ration_glj_facade.getLibOptionsForCompilation(req.session.sessionCompilation._id)
+            : await ration_glj_facade.getLibOptions(engineerID);
+            libData.push({ name: '补充工料机', gljLibId: COMPLEMENTARY_LIB });
+            if (gljLibId) { // 替换人材机初始化会触发此条件
+                const orgDefalutLib = libData.find(lib => lib.isDefault);
+                const newDefaultLib = libData.find(lib => lib.gljLibId === +gljLibId);
+                if (orgDefalutLib && newDefaultLib) {
+                    orgDefalutLib.isDefault = false;
+                    newDefaultLib.isDefault = true;
+                }
+            }
+        }
+        if (!gljLibId && libData) {
+            gljLibId = (libData.find(lib => lib.isDefault) || {}).gljLibId;
+        }
+        const info = gljLibId === COMPLEMENTARY_LIB 
+            ? { gljLibId: null, userID: req.session.sessionUser.id, compilationId: req.session.sessionCompilation._id }
+            : { gljLibId, userID: null, compilationId: null };
         ration_glj_facade.getGLJData(info,function (err,datas) {
             if(err){
                 result.error=1;
@@ -73,6 +100,7 @@ async function getGLJData(req, res) {
                 //多单价字段
                 if(req.session.sessionCompilation.priceProperties) datas.priceProperties = req.session.sessionCompilation.priceProperties;
                 result.datas = datas;
+                result.datas.libData = libData;
             }
             res.json(result);
         });
@@ -83,6 +111,30 @@ async function getGLJData(req, res) {
         res.json(result);
     }
 }
+/* async function getGLJData(req, res) {
+    let result={
+        error:0
+    }
+    try {
+        let info = await ration_glj_facade.getLibInfo(req);
+        ration_glj_facade.getGLJData(info,function (err,datas) {
+            if(err){
+                result.error=1;
+                result.message = err.message;
+            }else {
+                //多单价字段
+                if(req.session.sessionCompilation.priceProperties) datas.priceProperties = req.session.sessionCompilation.priceProperties;
+                result.datas = datas;
+            }
+            res.json(result);
+        });
+    }catch (err){
+        logger.err(err);
+        result.error=1;
+        result.message = err.message;
+        res.json(result);
+    }
+} */
 
 async function addGLJ(req, res){
     let result={

+ 64 - 0
modules/ration_glj/facade/ration_glj_facade.js

@@ -8,6 +8,8 @@ module.exports = {//先 exports再require 防止循环引用
     deleteByRation: deleteByRation,
     getQuantityByProjectGLJ: getQuantityByProjectGLJ,
     getLibInfo: getLibInfo,
+    getLibOptions,
+    getLibOptionsForCompilation,
     getGLJData: getGLJData,
     getGLJDataByCodes:getGLJDataByCodes,
     addGLJ: addGLJ,
@@ -57,6 +59,9 @@ const stdGljModel = mongoose.model('std_glj_lib_gljList');
 const gljClassModel = mongoose.model('std_glj_lib_gljClass');
 const projectDao = require('../../pm/models/project_model').project;
 const compleClassModel = mongoose.model('complementary_glj_section');
+const stdRationLibModel = mongoose.model('std_ration_lib_map');
+const compilationModel = mongoose.model('compilation');
+const engineeringModel = mongoose.model('engineering_lib');
 let gljUtil = require('../../../public/gljUtil');
 
 
@@ -548,6 +553,65 @@ async function getGLJLibByEngineerID  (engineerID) {
     return gljLibId
 }
 
+// 获取人材机选择页面,可选的定额库-人材机库映射选项
+async function getLibOptions(engineerID) {
+    // 找到工程专业绑定的定额库,再获取这些定额库引用的人材机库
+    const engineeringLibModel = new EngineeringLibModel();
+    const engineeringInfo = await engineeringLibModel.findDataByCondition({ _id: engineerID });
+    const rationLibs = engineeringInfo.ration_lib;
+    const rationLibIDs = rationLibs.map(lib => lib.id);
+    const rationLibData = await stdRationLibModel.find({ ID: { $in: rationLibIDs } }, 'ID gljLib').lean();
+    const rst = [];
+    rationLibs.forEach(lib => {
+        rationLibData.forEach(stdLib => {
+            if (+lib.id === +stdLib.ID) {
+                lib.gljLibId = stdLib.gljLib;
+                rst.push(lib);
+            }
+        });
+    });
+    return rst;
+}
+
+// 获取人材机选择库页面,可选的定额库为费用定额下,所有工程专业的定额库(需要去重)
+async function getLibOptionsForCompilation(compilationId) {
+    const compilation = await compilationModel.findOne({ _id: mongoose.Types.ObjectId(compilationId) }, 'ration_valuation bill_valuation');
+    const valuationIDs = [];
+    if (compilation.ration_valuation[0] && compilation.ration_valuation[0].enable) {
+        valuationIDs.push(compilation.ration_valuation[0].id);
+    }
+    if (compilation.bill_valuation[0] && compilation.bill_valuation[0].enable) {
+        valuationIDs.push(compilation.bill_valuation[0].id);
+    }
+    const engineeringLibs = await engineeringModel.find({ valuationID: { $in: valuationIDs }, visible: true }, 'ration_lib');
+    const rationLibs = [];
+    const rationLibIDs = [];
+    let hasDefalut = false;
+    engineeringLibs.forEach(lib => {
+        lib.ration_lib.forEach(rLib => {
+            if (!rationLibIDs.includes(rLib.id)) {
+                rationLibIDs.push(rLib.id);
+                rationLibs.push({
+                    isDefault: hasDefalut ? false: rLib.isDefault,
+                    name: rLib.name,
+                    id: rLib.id
+                });
+                if (rLib.isDefault) {
+                    hasDefalut = true;
+                }
+            }
+        });
+    });
+    const stdRationLibs = await stdRationLibModel.find({ ID: { $in: rationLibIDs } }, 'ID gljLib').lean();
+    rationLibs.forEach(lib => {
+        stdRationLibs.forEach(stdLib => {
+            if (+lib.id === +stdLib.ID) {
+                lib.gljLibId = stdLib.gljLib;
+            }
+        });
+    });
+    return rationLibs;
+}
 
 function getGLJData(info, callback) {
     let gljDao = new GljDao();

+ 1 - 1
modules/ration_glj/routes/ration_glj_route.js

@@ -8,7 +8,7 @@ let rgController = require('../controllers/ration_glj_controller');
 module.exports = function (app) {
 
     var rgRouter = express.Router();
-    rgRouter.get('/getGLJData/:engineerID', rgController.getGLJData);
+    rgRouter.get('/getGLJData/:engineerID/:gljLibId/:isInitial', rgController.getGLJData);
     rgRouter.post('/getGLJDataByCodes',rgController.getGLJDataByCodes);
     rgRouter.post('/addGLJ',rgController.addGLJ);
     rgRouter.post('/replaceGLJ',rgController.replaceGLJ);

+ 32 - 23
modules/reports/controllers/rpt_controller.js

@@ -428,7 +428,6 @@ function getMultiRptsCommon(user_id, prj_id, rpt_ids, pageSize, orientation, cus
 function getBillsSummaryReportPages(req, user_id, prjIds, rpt_id, pageSize, orientation, customizeCfg, option, outputType, cb) {
     let rptTpl = null;
     rptTplDataFacade.getBudgetSummayDatas(prjIds, req.session.sessionCompilation.overWriteUrl).then(function(summaryRawDataRst) {
-        // console.log(summaryRawDataRst);
         rptTplFacade.getRptTemplate(rpt_id).then(function(rptTpl) {
             let rptDataUtil = new rptDataExtractor();
             rptDataUtil.initialize((rptTpl._doc)?rptTpl._doc:rptTpl);
@@ -461,8 +460,8 @@ function getBillsSummaryReportPages(req, user_id, prjIds, rpt_id, pageSize, orie
                 cb('Exception occurs while on going...', null);
             }
         });
-
     });
+
 }
 
 function getSummaryComboPages(req, user_id, prjIds, billsSummaryRpt_ids, gljSummaryRpt_ids, pageSize, orientation, customizeCfg, option, outputType, cb) {
@@ -507,38 +506,44 @@ function getSummaryComboPages(req, user_id, prjIds, billsSummaryRpt_ids, gljSumm
         }
         if (billRpts.length > 0) {
             rptTplDataFacade.getBudgetSummayDatas(prjIds, req.session.sessionCompilation.overWriteUrl).then(function(summaryRawDataRst) {
-                let savedBillsData = [];
-                Object.assign(savedBillsData, summaryRawDataRst.SummaryAuditDetail);
-                for (let idx = 0; idx < billRpts.length; idx++) {
-                    pri_setup_rpt_tpl_data(billRpts[idx], summaryRawDataRst);
-                    if (idx < billRpts.length - 1) {
-                        Object.assign(summaryRawDataRst.SummaryAuditDetail, savedBillsData);
+                // let savedBillsData = [];
+                try {
+                    // Object.assign(savedBillsData, summaryRawDataRst.SummaryAuditDetail);
+                    for (let idx = 0; idx < billRpts.length; idx++) {
+                        pri_setup_rpt_tpl_data(billRpts[idx], summaryRawDataRst);
+                        // if (idx < billRpts.length - 1) {
+                        //     Object.assign(summaryRawDataRst.SummaryAuditDetail, savedBillsData);
+                        // }
                     }
-                }
-                if (gljRpts && gljRpts.length > 0) {
-                    rptTplDataFacade.getGLJSummayDatas(prjIds).then(function(summaryRawDataRst) {
-                        let savedBillsData = [];
-                        Object.assign(savedBillsData, summaryRawDataRst.SummaryAuditDetail);
-                        for (let idx = 0; idx < gljRpts.length; idx++) {
-                            pri_setup_rpt_tpl_data(gljRpts[idx], summaryRawDataRst);
-                            if (idx < gljRpts.length - 1) {
-                                Object.assign(summaryRawDataRst.SummaryAuditDetail, savedBillsData);
+                    if (gljRpts && gljRpts.length > 0) {
+                        rptTplDataFacade.getGLJSummayDatas(prjIds).then(function(summaryRawDataRst) {
+                            // let savedBillsData = [];
+                            // Object.assign(savedBillsData, summaryRawDataRst.SummaryAuditDetail);
+                            for (let idx = 0; idx < gljRpts.length; idx++) {
+                                pri_setup_rpt_tpl_data(gljRpts[idx], summaryRawDataRst);
+                                // if (idx < gljRpts.length - 1) {
+                                //     Object.assign(summaryRawDataRst.SummaryAuditDetail, savedBillsData);
+                                // }
                             }
-                        }
+                            cb(null, pageRstArr);
+                        });
+                    } else {
                         cb(null, pageRstArr);
-                    });
-                } else {
+                    }
+                } catch (ex) {
+                    console.log(ex);
                     cb(null, pageRstArr);
                 }
             });
         } else if (gljRpts.length > 0) {
             rptTplDataFacade.getGLJSummayDatas(prjIds).then(function(summaryRawDataRst) {
-                let savedBillsData = [];
-                Object.assign(savedBillsData, summaryRawDataRst.SummaryAuditDetail);
+                // let savedBillsData = [];
+                // Object.assign(savedBillsData, summaryRawDataRst.SummaryAuditDetail);
+                // 养护工料机汇总不用考虑back up问题。模板需要自觉一点,不要修改数据!!!
                 for (let idx = 0; idx < gljRpts.length; idx++) {
                     pri_setup_rpt_tpl_data(gljRpts[idx], summaryRawDataRst);
                     if (idx < gljRpts.length - 1) {
-                        Object.assign(summaryRawDataRst.SummaryAuditDetail, savedBillsData);
+                        // Object.assign(summaryRawDataRst.SummaryAuditDetail, savedBillsData);
                     }
                 }
                 cb(null, pageRstArr);
@@ -919,6 +924,10 @@ module.exports = {
                 }
             });
         } else if ((rpt_bill_tpl_ids && rpt_bill_tpl_ids.length > 0) || (rpt_glj_tpl_ids && rpt_glj_tpl_ids.length > 0)) {
+            // console.log('rpt_bill_tpl_ids:');
+            // console.log(rpt_bill_tpl_ids);
+            // console.log('rpt_glj_tpl_ids:');
+            // console.log(rpt_glj_tpl_ids);
             getSummaryComboPages(req, user_id, prjIds, rpt_bill_tpl_ids, rpt_glj_tpl_ids, pageSize, orientation, customizeCfg, option, JV.OUTPUT_TYPE_NORMAL, function (err, rptSumPageRstArray) {
                 let parallelFunctions = [];
                 pri_Add_Parallel_Functions(parallelFunctions, rptSumPageRstArray, sum_rpt_names, err);

+ 50 - 0
modules/unit_price_file/controllers/unit_price_controller.js

@@ -0,0 +1,50 @@
+
+let mongoose = require("mongoose")
+let logger = require("../../../logs/log_helper").logger;
+let config = require("../../../config/config.js");
+let unitPriceFileModel = mongoose.model('unit_price_file');
+let projectModel = mongoose.model('projects');
+const ProjectDao = require('../../pm/models/project_model').project;
+let unitPriceModel = mongoose.model('unit_price');
+let mixRatioModel = mongoose.model('mix_ratio');
+let glj_type_util = require('../../../public/cache/std_glj_type_util');
+let _ = require("lodash");
+
+module.exports={
+    index:async function(req,res){
+      let unitPriceFileID = req.params.unitPriceFileID;
+      let unitPriceFile = await unitPriceFileModel.findOne({id:unitPriceFileID}).lean();
+      let project = await projectModel.findOne({ID:unitPriceFile.root_project_id}).lean();
+      let tenderData = await ProjectDao.getTenderByUnitPriceFileId(unitPriceFileID);
+      let unitpriceList = await unitPriceModel.find({unit_price_file_id:unitPriceFileID},{supplyLocation:0}).lean();
+      let mixRatioList = await mixRatioModel.find({unit_price_file_id:unitPriceFileID}).lean();
+      let mixRatioMap = _.groupBy(mixRatioList,"connect_key");
+
+
+
+      let gljTypeMap = glj_type_util.getStdGljTypeCacheObj().innerGljTypeObj;
+      let usedTenderList = [];
+      if (tenderData !== null) {
+          for (let tmp of tenderData) {
+              usedTenderList.push(tmp.name);
+          }
+      }
+      let usedTenderString = "人材机单价的变化,将自动影响以下单位工程造价:<br>"+usedTenderList.join("<br>");
+      res.render('building_saas/unit_price_file/index.html',
+        {
+          userAccount: req.session.userAccount,
+          userID: req.session.sessionUser.id,
+          versionName: req.session.compilationVersion,
+          unitFileName:unitPriceFile.name,
+          rootProjectName:project.name,
+          usedTenderList:usedTenderList,
+          usedTenderString:usedTenderString,
+          unitpriceList:JSON.stringify(unitpriceList),
+          gljTypeMap:JSON.stringify(gljTypeMap),
+          mixRatioMap:JSON.stringify(mixRatioMap),
+          LicenseKey:config.getLicenseKey(process.env.NODE_ENV)
+        });
+    }
+}
+
+// engineerID = req.params.engineerID;

+ 14 - 0
modules/unit_price_file/routes/unit_price_router.js

@@ -0,0 +1,14 @@
+let express = require('express');
+let unitPirceController = require('../controllers/unit_price_controller');
+
+module.exports = function (app) {
+
+    var Router = express.Router();
+    Router.get('/index/:unitPriceFileID', unitPirceController.index);
+    // Router.post('/getGLJDataByCodes',unitPirceController.getGLJDataByCodes);
+    // Router.post('/addGLJ',unitPirceController.addGLJ);
+    // Router.post('/replaceGLJ',unitPirceController.replaceGLJ);
+    
+
+    app.use('/unitPrice',Router);
+}

+ 9 - 1
public/common_constants.js

@@ -77,7 +77,15 @@
         REPAIR_MAINTENANCE_FEE: 33,
     };
 
+    // 补充人材机库
+    const COMPLEMENTARY_LIB = 'complementaryLib';
+
+    // 费用定额
+    const COMPILATION = 'compilation';
+
     return {
-        fixedFlag
+        fixedFlag,
+        COMPLEMENTARY_LIB,
+        COMPILATION,
     };
 })

+ 6 - 8
public/web/gljUtil.js

@@ -265,12 +265,9 @@ let gljUtil = {
         if (!this.isConcreteType(glj.unit_price.type)&& this.notEditType.indexOf(glj.unit_price.type)!=-1&&glj.ratio_data.length>0) {//对于机械台班等有组成物的材料,价格需根据组成物计算得出(排除混凝土、配合比、砂浆这几个类型直接为0)。
             let p =0;
             for(let ratio of glj.ratio_data){
-                let tem =  _.find(projectGLJDatas.gljList,{
-                    'code': ratio.code,
-                    'name': ratio.name,
-                    'specs':ratio.specs,
-                    'type': ratio.type,
-                    'unit': ratio.unit
+                let rIndex = gljUtil.getIndex(ratio);
+                let tem =  _.find(projectGLJDatas.gljList,function(item){
+                  return rIndex == gljUtil.getIndex(item);
                 });
                 if(tem){
                     let priceData=this.getGLJPrice(tem,projectGLJDatas,calcOptions,labourCoeDatas,decimalObj,true,_,scMathUtil);
@@ -399,8 +396,9 @@ let gljUtil = {
         let lo = lodash?lodash:_;
         let specialMap = {1:-1,303:0,202:9,203:10,204:11};//,人工、机械工排在最前,混凝土、砂浆、配合比 排到最后
         list = lo.sortByAll(list, [function (item) {
-            if(specialMap[item.unit_price.type] != undefined) return specialMap[item.unit_price.type];
-            return gljUtil.getMainType(item.unit_price.type);
+            let unit_price = item.unit_price?item.unit_price:item;
+            if(specialMap[unit_price.type] != undefined) return specialMap[unit_price.type];
+            return gljUtil.getMainType(unit_price.type);
         }, gljUtil.getCodeSortMath()]);
         return list;
     },

+ 6 - 5
public/web/sheet/sheet_common.js

@@ -132,13 +132,14 @@ var sheetCommonObj = {
             if (setting.header[col].formatter) {
                 sheet.setFormatter(-1, col, setting.header[col].formatter, GC.Spread.Sheets.SheetArea.viewport);
             }
-            if (setting.header[col].cellType === "checkBox" || setting.header[col].cellType === "button") {//clear and reset
+           /*  直接在showrowdata时当val为null时返回一个text类型的单元格 
+              if (setting.header[col].cellType === "checkBox" || setting.header[col].cellType === "button") {//clear and reset
                 var me = this, header = GC.Spread.Sheets.SheetArea.colHeader;
                 sheet.deleteColumns(col, 1);
                 sheet.addColumns(col, 1);
                 sheet.setValue(0, col, setting.header[col].headerName, header);
                 sheet.setColumnWidth(col, setting.header[col].headerWidth ? setting.header[col].headerWidth : 100);
-            }
+            } */
             if (setting.header[col].visible !== null && setting.header[col].visible !== undefined) {
                 sheet.setColumnVisible(col, setting.header[col].visible);
             }
@@ -177,7 +178,7 @@ var sheetCommonObj = {
                     val = val + '';
                 }
             }
-            if (val != null && setting.header[col].cellType === "checkBox") {
+            if (setting.header[col].cellType === "checkBox") {
                 this.setCheckBoxCell(row, col, sheet, val)
             }
             if (setting.header[col].cellType === "comboBox") {
@@ -301,8 +302,8 @@ var sheetCommonObj = {
         }
     },
     setCheckBoxCell(row, col, sheet, val) {
-        var c = new GC.Spread.Sheets.CellTypes.CheckBox();
-        c.isThreeState(false);
+        var c = val==null?new GC.Spread.Sheets.CellTypes.Text():new GC.Spread.Sheets.CellTypes.CheckBox();
+        if(val != null) c.isThreeState(false);
         sheet.setCellType(row, col, c, GC.Spread.Sheets.SheetArea.viewport);
         sheet.getCell(row, col).value(val);
         sheet.getCell(row, col).hAlign(GC.Spread.Sheets.HorizontalAlign.center);

+ 10 - 2
web/building_saas/complementary_ration_lib/html/dinge.html

@@ -18,6 +18,10 @@
     <link rel="shortcut icon" href="/web/building_saas/css/favicon.ico">
     <link rel="icon" type="image/gif" href="/web/building_saas/css/animated_favicon1.gif">
     <style type="text/css">
+        .form-control-inline {
+            display: inline-block !important;
+            width: 80% !important;
+        }
         div.resize-y{
             height: 5px;
             background: #efefef;
@@ -520,8 +524,12 @@
             <div class="modal-body" style="padding-left: 0; padding-right: 3px; margin-left: 0;">
                 <div style="width: 36%; float: left;">
                     &nbsp;
-                    <input type="radio" class="glj-radio" name="glj" value="stdGljs">标准&nbsp;&nbsp;
-                    <input type="radio" class="glj-radio" name="glj" value="complementaryGljs">补充&nbsp;&nbsp;
+                    <select class="form-control  form-control-sm form-control-inline" id="glj-lib-select">
+                        <option value="1">1</option>
+                        <option value="2">2</option>
+                    </select>
+<!--                     <input type="radio" class="glj-radio" name="glj" value="stdGljs">标准&nbsp;&nbsp;
+                    <input type="radio" class="glj-radio" name="glj" value="complementaryGljs">补充&nbsp;&nbsp; -->
                     <div  class="modal-auto-height" id="gljSelTreeDiv" style="overflow: hidden">
                         <div style="width: 100%; height: 100%; overflow: auto">
                             <ul id="selGljTree" class="ztree"></ul>

+ 67 - 84
web/building_saas/complementary_ration_lib/js/gljSelect.js

@@ -3,10 +3,10 @@
  */
 
 let gljSelOprObj = {
+    distTypeTree: null,
     parentNodeIds: {},
     treeObj:null,
     rootNode: null,//分类树根节点
-    radiosSelected: null,//allGljs, stdGljs, complementaryGljs
     workBook: null,
     selectedList: [],//选中的工料机
     setting: {
@@ -39,23 +39,6 @@ let gljSelOprObj = {
             delete glj.ID;
         }
     },
-    getSelGljItems: function(gljData) {
-        this.stdGljList = gljData.stdGljs;
-        //兼容多单价,计算补充定额价格时,套多单价人材机的时候,默认取第一个价格
-        for(let sGlj of this.stdGljList){
-            if(sGlj.priceProperty && typeof sGlj.priceProperty.price1 !== 'undefined'){
-                sGlj.basePrice = sGlj.priceProperty.price1;
-            }
-        }
-        this.complementaryGljList = gljData.complementaryGljs;
-        this.switchToGljId(this.stdGljList);
-        this.switchToGljId(this.complementaryGljList);
-        this.setProp('type', 'std', this.stdGljList);
-        this.setProp('type', 'complementary', this.complementaryGljList);
-        this.sortGlj(this.stdGljList);
-        this.sortGlj(this.complementaryGljList);
-        gljAdjOprObj.gljList = this.stdGljList.concat(this.complementaryGljList);
-    },
     initClassTree: function (type, treeData) {
         let me = this;
         if (me.treeObj) {
@@ -75,28 +58,6 @@ let gljSelOprObj = {
             }
         }
     },
-    getGljClassTree: function (gljLibId, callback) {
-        let me = this;
-        let url = '/complementartGlj/api/getMixedTree';
-        let postData = {gljLibId: gljLibId};
-        let sucFunc = function (rstData) {
-            me.treeData = rstData;
-            me.initClassTree('std', me.treeData.std);
-            gljSelOprObj.buildSheet($('#gljSelSheet')[0]);
-            if(callback){
-                callback();
-            }
-        };
-        let errFunc = function () {
-
-        };
-        CommonAjax.post(url, postData, sucFunc, errFunc);
-    },
-    getGljClassTree: function (mixedTreeData) {
-        this.treeData = mixedTreeData;
-        this.initClassTree('std', this.treeData.std);
-        gljSelOprObj.buildSheet($('#gljSelSheet')[0]);
-    },
     buildSheet: function (container) {
         let me = gljSelOprObj;
         me.workBook = sheetCommonObj.buildSheet(container, me.setting, 30);
@@ -107,7 +68,64 @@ let gljSelOprObj = {
         me.workBook.getSheet(0).bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
         me.workBook.bind(GC.Spread.Sheets.Events.ButtonClicked, me.onButtonClicked);//复选框点击事件
         me.bindBtnOpr($('#gljSelY'));
-        me.radiosChange();
+    },
+    setGLJItems: function(stdGLJs, complementaryGLJs) {
+        this.stdGljList = stdGLJs;
+        //兼容多单价,计算补充定额价格时,套多单价人材机的时候,默认取第一个价格
+        for(let sGlj of this.stdGljList){
+            if(sGlj.priceProperty && typeof sGlj.priceProperty.price1 !== 'undefined'){
+                sGlj.basePrice = sGlj.priceProperty.price1;
+            }
+        }
+        this.complementaryGljList = complementaryGLJs;
+        this.switchToGljId(this.stdGljList);
+        this.switchToGljId(this.complementaryGljList);
+        this.setProp('type', 'std', this.stdGljList);
+        this.setProp('type', 'complementary', this.complementaryGljList);
+        this.sortGlj(this.stdGljList);
+        this.sortGlj(this.complementaryGljList);
+    },
+    initLibOptions: function (libData) {
+        const html = libData.reduce((acc, lib) => acc += `<option ${lib.isDefault ? 'selected="selected"' : ''} value="${lib.gljLibId}">${lib.name}</option>`, '');
+        $('#glj-lib-select').html(html);
+    },
+    // 初始化选择页面
+    initView: async function (gljLibId, isInitial) {
+        try {
+            $.bootstrapLoading.start();
+            const { libData, treeData, distTypeTree, stdGLJ, complementaryGLJs } = await this.getViewData(gljLibId);
+            if (isInitial) {
+                this.initLibOptions(libData);
+                $('#gljSearchKeyword').val('');
+                setTimeout(() => $('#selGlj').modal('show'), 200);
+            }
+            if (!this.workBook) {
+                this.buildSheet($('#gljSelSheet')[0]);
+            }
+            this.distTypeTree = distTypeTree;
+            this.setGLJItems(stdGLJ, complementaryGLJs);
+            this.selectedList = [].concat(rationGLJOprObj.cache['_GLJ_' + rationGLJOprObj.currentRationItem.ID]);
+            this.showGljList = [];
+            this.setShowGljList(this.stdGljList, true);
+            if (treeData.std.length) {
+                this.initClassTree('std', treeData.std);
+            } else if (treeData.comple.length) {
+                this.initClassTree('comple', treeData.comple);
+            } else {
+                throw '没有有效的分类树。';
+            }
+            this.filterDatasAndShow();
+        } catch (err) {
+            console.log(err);
+            alert(err);
+        } finally {
+            $.bootstrapLoading.end();
+        }
+    },
+    getViewData: async function (gljLibId) {
+        const url = `/rationGlj/getGLJData/${commonConstants.COMPILATION}/${gljLibId}/true`;
+        const data = await ajaxGet(url);
+        return data.datas;
     },
     onClipboardPasting: function (sender, args) {
         args.cancel = true;
@@ -172,41 +190,16 @@ let gljSelOprObj = {
             me.showGljList.push(gljList[i]);
         }
     },
-    //初始默认radio
-    initRadio: function () {
-        let me = gljSelOprObj;
-        $('#gljSearchKeyword').val('');//恢复搜索文本
-        me.selectedList = [].concat(rationGLJOprObj.cache['_GLJ_' + rationGLJOprObj.currentRationItem.ID]);
-        //默认radio所有工料机
-        if(typeof $("input[name='glj']:checked")[0] !== 'undefined'){
-            $("input[name='glj']:checked")[0].checked = false;
-        }
-        $("input[value = 'stdGljs']")[0].checked = true;
-        me.radiosSelected = 'stdGljs';
-        //初始为标准工料机
-        me.showGljList = [];
-        if(me.radiosSelected === 'stdGljs'){
-            me.setShowGljList(me.stdGljList, true);
-            //me.setShowGljList(me.complementaryGljList, true);
-            me.sortGlj(me.showGljList);
-        }
-    },
     filterDatasAndShow: function () {
+        const gljLib = $('#glj-lib-select').val();
         let me = gljSelOprObj;
-        let val = $("input[name='glj']:checked").val();
-        me.radiosSelected = val;
         //选择改变,数据重新筛选显示
         me.showGljList = [];
-        if(me.radiosSelected === 'allGljs'){
-            me.setShowGljList(me.stdGljList);
+        if (gljLib === commonConstants.COMPLEMENTARY_LIB) {
             me.setShowGljList(me.complementaryGljList);
-        }
-        else if(me.radiosSelected === 'stdGljs'){
+        } else {
             me.setShowGljList(me.stdGljList);
         }
-        else if(me.radiosSelected === 'complementaryGljs'){
-            me.setShowGljList(me.complementaryGljList);
-        }
         //搜索匹配
         let searchStr = $('#gljSearchKeyword').val();
         if(searchStr && searchStr.trim() != ''){
@@ -215,10 +208,9 @@ let gljSelOprObj = {
                 return reg.test(data.code) || reg.test(data.name);
             });
         }
-        me.sortGlj(me.showGljList);
+        //me.sortGlj(me.showGljList);
         //重新显示
         me.showGljItems(me.showGljList, me.gljCurTypeId);
-        //切换radio后更新cache
         if (me.currentOprParent = 1) {
             if(me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]){
                 me.currentCache = me.getParentCache(me.parentNodeIds["_pNodeId_" + me.gljCurTypeId]);
@@ -230,19 +222,6 @@ let gljSelOprObj = {
             me.currentCache = me.getCache();
         }
     },
-    //监听radios选择事件
-    radiosChange: function () {
-        let me = gljSelOprObj;
-        $('.glj-radio').change(function () {
-            if($(this).val() === 'stdGljs') {
-                me.initClassTree('std', me.treeData.std);
-            } else {
-                me.initClassTree('comple', me.treeData.comple);
-            }
-            me.filterDatasAndShow();
-        });
-    },
-
     getParentCache: function (nodes) {
         let me = gljSelOprObj, rst = [];
         for(let i = 0; i < me.showGljList.length; i++){
@@ -349,6 +328,10 @@ let gljSelTreeOprObj = {
 };
 
 $(document).ready(function () {
+    $('#glj-lib-select').change(function () {
+        const gljLibId = $(this).val();
+        gljSelOprObj.initView(gljLibId, false);
+    });
     $('#gljSearchKeyword').change(function () {
         gljSelOprObj.filterDatasAndShow();
     });

+ 1 - 0
web/building_saas/complementary_ration_lib/js/init.js

@@ -40,6 +40,7 @@ const initialization = (() => {
                 rdSpreadEscSheets.push({sheet: rdSpread.getSheet(2), editStarting: rationCoeOprObj.onEditStarting, editEnded: rationCoeOprObj.onEditEnded});
                 rdSpreadEscSheets.push({sheet: rdSpread.getSheet(3), editStarting: rationInstObj.onEditStarting, editEnded: rationInstObj.onEditEnded});
                 sheetCommonObj.bindEscKey(rdSpread, rdSpreadEscSheets);
+                gljAdjOprObj.gljList = data.mixedGLJData.stdGljs.concat(data.mixedGLJData.complementaryGljs);
                 pageOprObj.initPage();
 
                 $("#linkGLJ").click(function(){

+ 1 - 6
web/building_saas/complementary_ration_lib/js/ration_glj.js

@@ -113,12 +113,7 @@ var rationGLJOprObj = {
                         items: {
                             "add": {
                                 name: "添加工料机", disabled: addDis, icon: "fa-plus", callback: function (key, opt) {
-                                    //默认radio所有工料机
-                                    gljSelOprObj.initRadio();
-                                    gljSelOprObj.gljCurTypeId = null;
-                                    gljSelOprObj.initClassTree('std', gljSelOprObj.treeData.std);
-                                    //弹出窗口
-                                    $('#selGlj').modal('show');
+                                    gljSelOprObj.initView(0, true);
                                 }
                             },
                             "delete": {

+ 0 - 2
web/building_saas/complementary_ration_lib/js/section_tree.js

@@ -20,8 +20,6 @@ let pageOprObj = {
         $('#fzAddConBtn').click(annotationOprObj.bindAddConBtn());
         $('#fzUpdateConBtn').click(annotationOprObj.bindUpdateConBtn());
         annotationOprObj.bindAllEvents($('#fzTxtareaAll'));
-        gljSelOprObj.getGljClassTree(this.mixedTreeData);
-        gljSelOprObj.getSelGljItems(this.mixedGLJData);
     },
     getRationLibInfo: function (rationLibId, callback) {
         CommonAjax.post('api/getRationLib', {rationRepId: rationLibId}, callback);

+ 4 - 0
web/building_saas/css/custom.css

@@ -432,6 +432,10 @@ input.text-right{
     height: 1000px; 
     background: #f7f7f9;
 }
+.form-control-inline {
+  display: inline-block !important;
+  width: 80% !important;
+}
 .unit_price_header{
   padding-top:6px;
   margin-left: 50px;

+ 4 - 0
web/building_saas/css/main.css

@@ -56,6 +56,10 @@ font-size: .875rem;
 height: calc(1.5em + .5rem + 2px);
 font-size: .875rem;
 }
+.btn-xs{
+  padding:0rem .5rem;
+  font-size:.875rem;
+}
 /*自定义css*/
 .login-body,.login-html{
 height:100%;

+ 1 - 0
web/building_saas/glj/html/project_glj.html

@@ -14,6 +14,7 @@
                 <option>福建车船税标准(2012)</option>
             </select>
         </div>
+        <a class="btn btn-sm ml-1" id="editUnitFile" href="/unitPrice/index/123" target="_"> 编辑单价文件</a>
     </div>
 
 </div>

+ 5 - 3
web/building_saas/main/html/main.html

@@ -42,7 +42,7 @@
         let projectReadOnly = JSON.parse('<%- projectReadOnly %>');
         let projectCooperate = JSON.parse('<%- projectCooperate %>');
         let projectOptins =  JSON.parse('<%- options %>');
-        const G_SHOW_BLOCK_LIB = false;
+        const G_SHOW_BLOCK_LIB = true;
 //        const G_SHOW_BLOCK_LIB = false;
     </script>
 </head>
@@ -1069,8 +1069,10 @@
                 <div class="modal-body" style="padding-left: 0; padding-right: 3px; margin-left: 0;">
                         <div style="width: 32%; float: left;">
                             &nbsp;
-                            <input type="radio" class="glj-radio" name="glj" value="stdGLJ">标准&nbsp;&nbsp;
-                            <input type="radio" class="glj-radio" name="glj" value="complementaryGLJs">补充&nbsp;&nbsp;
+                            <select class="form-control  form-control-sm form-control-inline" id="glj-lib-select">
+                            </select>
+ <!--                            <input type="radio" class="glj-radio" name="glj" value="stdGLJ">标准&nbsp;&nbsp;
+                            <input type="radio" class="glj-radio" name="glj" value="complementaryGLJs">补充&nbsp;&nbsp; -->
                             <div  class="modal-auto-height" id="componentTreeDiv" style=" height: 435px; overflow: hidden;">
                                 <!--<div class="print-list">-->
                                 <div style="width: 100%; height: 100%; overflow: auto">

+ 27 - 8
web/building_saas/main/js/models/project_glj.js

@@ -431,14 +431,16 @@ ProjectGLJ.prototype.materialCal = function (id,dataMap,tglj,tfreightList,tprice
     if(!glj) return;
     let unitPrice = {projectGLJID:glj.id,id:glj.unit_price.id,'unit_price_file_id':glj.unit_price.unit_price_file_id,doc:{}};
     //先计算原价
-    let [originalPrice,supplyLocation] = this.priceCalc(glj,dataMap,tpriceList);
+    let [originalPrice,supplyLocation,priceHeightFee] = this.priceCalc(glj,dataMap,tpriceList);
     doc['originalPrice'] = originalPrice+'';
     doc['supplyLocation'] = supplyLocation;
+    doc['priceHeightFee'] = priceHeightFee;
     //再计算运费
     let grossWeightCoe_n = doc['grossWeightCoe_n']?doc['grossWeightCoe_n']:glj.unit_price.grossWeightCoe_n;
     grossWeightCoe_n = scMathUtil.roundForObj(grossWeightCoe_n,process);
-    let unitFreight = this.freightCalc(glj,grossWeightCoe_n,dataMap,tfreightList);
+    let [unitFreight,freightHeightFee] = this.freightCalc(glj,grossWeightCoe_n,dataMap,tfreightList);
     doc['unitFreight'] = unitFreight+'';
+    doc['freightHeightFee'] = freightHeightFee+'';
     //计算场外运输损耗
     let sum_o_f = scMathUtil.roundForObj(originalPrice+unitFreight,process);//(原价+单位运费)
     let totalLoadingTimes = doc["totalLoadingTimes"]?doc["totalLoadingTimes"]:glj.unit_price.totalLoadingTimes;//装卸总次数
@@ -478,10 +480,12 @@ ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap,tfreigh
     let unitPirce = getDecimal("glj.unitPrice");
     let unitPriceHasMix = getDecimal("glj.unitPriceHasMix");//这里暂时没用到
     let sum = 0;
+    let height_sum=0;
     let freightList = tfreightList?tfreightList:_.filter(this.datas.freightList,{"connect_key":gljUtil.getIndex(glj)});
     if(dataMap["freight"] && dataMap["freight"]["add"])  freightList = freightList.concat(dataMap["freight"]["add"]); //把添加的加进去
     for(let f of freightList){
         let unitFreight = f.unitFreight,kmDistance = f.kmDistance,freightIncreaseRate = f.freightIncreaseRate,unitLoadingFee= f.unitLoadingFee,loadingTimes = f.loadingTimes,otherFee = f.otherFee,weightCoe = f.weightCoe,conveyance = f.conveyance,calcType=f.calcType,materialType=f.materialType;
+        let heightFee= f.heightFee?f.heightFee:0;  
         if(dataMap["freight"] && dataMap["freight"]["update"]){//覆盖更新的数据
             let t = dataMap["freight"]["update"][f.ID];
             if(t){
@@ -495,6 +499,7 @@ ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap,tfreigh
                 if(t['conveyance']) conveyance = t['conveyance'];
                 if(t['calcType']) calcType = t['calcType'];
                 if(t['materialType']) materialType = t['materialType'];
+                if(t['heightFee']) heightFee = t['heightFee'];
             }
         }
         if(dataMap["freight"] && dataMap["freight"]["delete"]){//忽略删除的数据
@@ -505,6 +510,7 @@ ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap,tfreigh
         freightIncreaseRate = scMathUtil.roundForObj(1+freightIncreaseRate/100,process);//(1+运距增加率%)
         unitFreight = scMathUtil.roundForObj(unitFreight,unitPirce);
         kmDistance = scMathUtil.roundForObj(kmDistance,unitPirce);
+        heightFee = scMathUtil.roundForObj(heightFee,unitPirce);
 
         let t = getPrice(unitFreight,kmDistance,conveyance,calcType,materialType,process);//单位运价×km运距
         t = scMathUtil.roundForObj(t*freightIncreaseRate,process);//单位运价×km运距×(1+运距增加率%)
@@ -519,12 +525,14 @@ ProjectGLJ.prototype.freightCalc= function (glj,grossWeightCoe_n,dataMap,tfreigh
         weightCoe = scMathUtil.roundForObj(weightCoe,unitPirce);
         t = scMathUtil.roundForObj(t*weightCoe,process);//(单位运价×km运距×(1+运距增加率%)+装卸费单价×装卸次数+其它费用)×单位毛重×加权系数
         sum = scMathUtil.roundForObj(sum + t,process);
+        heightFee = scMathUtil.roundForObj(heightFee*weightCoe,process);
+        height_sum = scMathUtil.roundForObj(height_sum + heightFee,process);
     }
     if(freightList.length == 0){//如果运费计算表没有数据,则读取输入的或单价文件的值
         let doc = dataMap['material']&&dataMap['material']['update']?dataMap['material']['update']:{};
         sum = doc['unitFreight']?doc['unitFreight']:glj.unit_price.unitFreight;
     }
-    return scMathUtil.roundForObj(sum,unitPirce);
+    return [scMathUtil.roundForObj(sum,unitPirce),scMathUtil.roundForObj(height_sum,unitPirce)];
 
 
     function getPrice(unitFreight,kmDistance,conveyance,calcType,materialType,process){
@@ -542,25 +550,31 @@ ProjectGLJ.prototype.priceCalc = function (glj,dataMap,tpriceList) {
     let unitPirce = getDecimal("glj.unitPrice");
     let unitPriceHasMix = getDecimal("glj.unitPriceHasMix");
     let original_price = 0;
+    let sumFeightFee = 0;
     let supplyList = [];
     let supplyLocation = "";
     let priceList = tpriceList?tpriceList:_.filter(this.datas.originalList,{"connect_key":gljUtil.getIndex(glj)});
     if(dataMap["price"] && dataMap["price"]["add"])  priceList = priceList.concat(dataMap["price"]["add"]); //把添加的加进去
     for(let p of priceList){
         let supplyPrice = p.supplyPrice ,coe = p.coe,supplyLocation=p.supplyLocation;
+        let heightFee = p.heightFee?p.heightFee:0;
         if(dataMap["price"] && dataMap["price"]["update"]){//覆盖更新的数据
             let t = dataMap["price"]["update"][p.ID];
             if(t && t["supplyPrice"]) supplyPrice =t["supplyPrice"];
             if(t && t["coe"]) coe =t["coe"];
             if(t && t["supplyLocation"]) supplyLocation = t["supplyLocation"];
+            if(t && t["heightFee"]) heightFee = t["heightFee"];
         }
         if(dataMap["price"] && dataMap["price"]["delete"]){//忽略删除的数据
             if(dataMap["price"]["delete"][p.ID]) continue;
         }
         supplyPrice = scMathUtil.roundForObj(supplyPrice,unitPirce);
         coe = scMathUtil.roundForObj(coe,unitPirce);
+        heightFee = scMathUtil.roundForObj(heightFee,unitPirce);
         let t_p = scMathUtil.roundForObj(supplyPrice *  coe,process);
+        let t_h = scMathUtil.roundForObj(heightFee *  coe,process);
         original_price=scMathUtil.roundForObj(original_price+t_p,process);
+        sumFeightFee = scMathUtil.roundForObj(sumFeightFee+t_h,process);
         supplyList.push(supplyLocation);
     }
     supplyLocation = supplyList.join(',');
@@ -569,7 +583,7 @@ ProjectGLJ.prototype.priceCalc = function (glj,dataMap,tpriceList) {
         original_price = doc['originalPrice']!==undefined?doc['originalPrice']:glj.unit_price.originalPrice;
         supplyLocation = doc['supplyLocation']!==undefined?doc['supplyLocation']:glj.unit_price.supplyLocation;
     }
-    return [scMathUtil.roundForObj(original_price,unitPriceHasMix),supplyLocation];
+    return [scMathUtil.roundForObj(original_price,unitPriceHasMix),supplyLocation,scMathUtil.roundForObj(sumFeightFee,unitPirce)];
 };
 
 
@@ -912,6 +926,7 @@ ProjectGLJ.prototype.calcEachFreightOrPrice = function (temp,type,priceMap) {//
     if(temp){
          if(type == "freight" && temp.conveyance !="自办运输") return null;
         let sum =0;
+        let heightFee = 0;
         let gljMap = {};
         let decimal = type == "freight"?getDecimal("glj.unitPrice"):getDecimal("glj.unitPriceHasMix");
         //因为材料计算的数据是保存在单价文件里的,有可能存在共享的情况,这样的话就不能用单价文件里的项目工料机ID来匹配,要用5大项匹配
@@ -926,18 +941,21 @@ ProjectGLJ.prototype.calcEachFreightOrPrice = function (temp,type,priceMap) {//
         }
         if(temp.rations) {
             for(let r of temp.rations){
-                sum = scMathUtil.roundForObj(sum + calcRation(r,gljMap[r.ID],pgljMap,priceMap),6);
+                let [tsum,thei] = calcRation(r,gljMap[r.ID],pgljMap,priceMap);
+                heightFee = scMathUtil.roundForObj(heightFee+thei,6);
+                sum = scMathUtil.roundForObj(sum + tsum,6);
             }
         }
         sum = scMathUtil.roundForObj(sum,decimal)+"";
-        if(type == "freight" && temp.unitFreight!= sum) return {ID:temp.ID,doc:{unitFreight:sum}};
-        if(type == "price" && temp.supplyPrice !=sum) return {ID:temp.ID,doc:{supplyPrice:sum}};
+        if(type == "freight" && temp.unitFreight!= sum) return {ID:temp.ID,doc:{unitFreight:sum,heightFee:heightFee}};
+        if(type == "price" && temp.supplyPrice !=sum) return {ID:temp.ID,doc:{supplyPrice:sum,heightFee:heightFee}}
     }
     return null;
 
 
     function calcRation(ration,gljs,pMap,priceMap){
         let result = 0;
+        let heightFee = 0;
         if(gljs){
             let processDecimal = getDecimal("process");
             let hightFeeRate = projectObj.project.projectGLJ.getHighlandFee(ration.feeType);//高原取费类别费率
@@ -960,8 +978,9 @@ ProjectGLJ.prototype.calcEachFreightOrPrice = function (temp,type,priceMap) {//
             let hs = scMathUtil.roundForObj(tt*hightFeeRate,processDecimal);//(人工定额消耗量*定额价*定额工程量+机械定额消耗量*定额价*定额工程量)*高原取费类别费率
             result = scMathUtil.roundForObj(as + result,processDecimal);
             result = scMathUtil.roundForObj(hs + result,processDecimal);
+            heightFee = hs;
         }
-        return  result;
+        return  [result,heightFee];
     }
 
 

+ 3 - 3
web/building_saas/main/js/models/ration_glj.js

@@ -538,10 +538,10 @@ let ration_glj = {
             }
             return node
         };
-        ration_glj.prototype.getGLJData = function (cb) {
+        ration_glj.prototype.getGLJData = function (url, cb) {
             let property = projectObj.project.projectInfo.property;
-            let engineerID = property.engineering_id;
-            CommonAjax.get('/rationGlj/getGLJData/'+engineerID, function (data) {
+            //let engineerID = property.engineering_id;
+            CommonAjax.get(url, function (data) {
                 //编办中有多单价设置
                 if(data.datas.priceProperties && data.datas.priceProperties.length > 0){
                     let tem = _.find(data.datas.priceProperties,{region:property.region,taxModel:parseInt(property.taxType)});

+ 13 - 76
web/building_saas/main/js/views/glj_view.js

@@ -998,12 +998,10 @@ var gljOprObj = {
     },
     filterLibGLJSheetData: function () {
         let me = this;
-        let val = $("input[name='glj']:checked").val();
-        if (val == 'allGljs') {
-            me.gljLibSheetData = me.stdGLJ.concat(me.complementaryGLJs);
-        } else {
-            me.gljLibSheetData = me[val];
-        }
+        const selectLibID = $('#glj-lib-select').val();
+        me.gljLibSheetData = selectLibID === commonConstants.COMPLEMENTARY_LIB
+            ? me.complementaryGLJs
+            : me.stdGLJ;
         if ($('#actionType').val() == 'replace' || $('#actionType').val() == 'm_replace') {
             me.filterLibGLJByType();
         }else if($('#actionType').val() == 'addMix'){
@@ -1432,7 +1430,10 @@ var gljOprObj = {
         let zTree = $.fn.zTree.getZTreeObj("gljTree");
         let node = null;
         if (ID) node = zTree.getNodesByParam('ID', ID, null)[0];
-        if (!node) node = zTree.getNodeByTId('gljTree_1');
+        if (!node) {
+            node = zTree.getNodeByTId('gljTree_1');
+            ID = node.ID;
+        }
         zTree.selectNode(node);
         gljOprObj.gljCurTypeId = ID;
         gljOprObj.filterLibGLJSheetData();
@@ -1537,72 +1538,7 @@ var gljOprObj = {
 
 $(function () {
     $('#glj_tree_div').on('shown.bs.modal', function (e) {
-        if (gljOprObj.gljLibSpresd == undefined) {
-            gljOprObj.gljLibSpresd = sheetCommonObj.buildSheet($('#gljLibSheet')[0], gljOprObj.gljLibSheetSetting, gljOprObj.stdGLJ.length + gljOprObj.complementaryGLJs.length);
-            sheetCommonObj.spreadDefaultStyle(gljOprObj.gljLibSpresd);
-            gljOprObj.gljLibSpresd.bind(GC.Spread.Sheets.Events.ButtonClicked, gljOprObj.onButtonClick);
-            gljOprObj.gljLibSheet = gljOprObj.gljLibSpresd.getSheet(0);
-            gljOprObj.gljLibSheet.bind(GC.Spread.Sheets.Events.SelectionChanged, gljOprObj.onSelectionChanged);
-            gljOprObj.gljLibSheet.setColumnWidth(0, 20, GC.Spread.Sheets.SheetArea.rowHeader);
-            gljOprObj.gljLibSheet.options.isProtected = true;
-            gljOprObj.gljLibSheet.name('glj_lib');
-        }
-        gljOprObj.gljLibSheetData = gljOprObj.AllRecode;
-        let gljClass = 0, selectMap = {};
-        if ($('#actionType').val() == 'add' || $('#actionType').val() == 'insert' || $('#actionType').val() == 'insertEquipment') {//插入,添加
-            gljOprObj.GLJSelection = [];
-        } else if($('#actionType').val() =='m_replace' || $('#actionType').val() == 'replace'){//替换、批量替换
-            let selected = gljOprObj.sheetData[gljContextMenu.selectedRow];
-            let connect_key = gljOprObj.getIndex(selected, gljKeyArray);
-            gljOprObj.GLJSelection = [connect_key];
-            selectMap[connect_key] = true;
-            gljOprObj.filterLibGLJByType();
-        }else if($('#actionType').val() =='addMix'){//添加组成物
-            gljOprObj.GLJSelection = [];
-            projectGljObject.filterLibGLJForMixRatio();
-            /*selections = projectGljObject.mixRatioData;  添加组成物的时候先不选中
-             gljOprObj.GLJSelection = [];
-             for(let s of selections){
-             let s_key = gljOprObj.getIndex(s, gljKeyArray);
-             selectMap[s_key] = true;
-             gljOprObj.GLJSelection.push(s_key);
-             }*/
-        }
-        for(let item of gljOprObj.gljLibSheetData){
-            let item_key = gljOprObj.getIndex(item, gljLibKeyArray);
-            if(selectMap[item_key]){
-                item.select = 1 ;
-                gljClass = item.gljClass;
-            }
-        }
-        //替换,焦点定位至当前选中人材机
-        if($('#actionType').val() =='m_replace' || $('#actionType').val() == 'replace'){
-            gljOprObj.locateZTree(gljClass);
-            let selected = gljOprObj.sheetData[gljContextMenu.selectedRow];
-            let index = _.findIndex(gljOprObj.gljLibSheetData, {code: selected.code});
-            gljOprObj.gljLibSheet.showRow(index, GC.Spread.Sheets.VerticalPosition.center);
-            gljOprObj.gljLibSheet.setActiveCell(index, 0);
-            gljOprObj.initSelection({row: index});
-            gljOprObj.gljLibSpresd.focus(true);
-        } else if ($('#actionType').val() === 'insertEquipment') {//右键插入设备,人材机选择窗口,应默认固定到分类"养护管理设备"。
-            let locateClass = gljOprObj.treeData.std.find(function (stdClass) {
-                return stdClass.Name === '养护管理设备';
-            });
-            if (locateClass) {
-                gljClass = locateClass.ID;
-                gljOprObj.locateZTree(gljClass);
-                gljOprObj.gljLibSheet.showRow(0, GC.Spread.Sheets.VerticalPosition.top);
-                gljOprObj.gljLibSheet.setActiveCell(0, 0);
-                gljOprObj.initSelection({row: 0});
-            }
-        } else if ($('#actionType').val() === 'add') {
-            gljOprObj.locateZTree(null);
-            gljOprObj.gljLibSheet.showRow(0, GC.Spread.Sheets.VerticalPosition.top);
-            gljOprObj.gljLibSheet.setActiveCell(0, 0);
-            gljOprObj.initSelection({row: 0});
-        } else {
-            gljOprObj.showLibGLJSheetData();
-        }
+        gljContextMenu.initGLJSelectView();
     });
 
     $('#mreplace_next_div').on('shown.bs.modal', function (e) {
@@ -1629,11 +1565,12 @@ $(function () {
                 gljOprObj.initClassTree('comple', gljOprObj.treeData.comple, true);
             }
             gljOprObj.initSelection({row: 0});
-            //gljOprObj.gljLibSheetData = gljOprObj[val];
-            /*gljOprObj.filterLibGLJSheetData();
-             gljOprObj.showLibGLJSheetData();*/
         }
     });
+    // 更改选择库
+    $('#glj-lib-select').change(function () {
+        getGLJData('change', false);
+    })
     /*    //工料机搜索
      $('#gljSearchKeyword').change(function () {
      gljOprObj.filterLibGLJSheetData();

+ 113 - 18
web/building_saas/main/js/views/glj_view_contextMenu.js

@@ -370,13 +370,101 @@ var gljContextMenu = {
         }
         //controller.setTreeSelected(controller.tree.items[target.row]);
         return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+    },
+    initGLJSelectView: function () {
+        if (gljOprObj.gljLibSpresd == undefined) {
+            gljOprObj.gljLibSpresd = sheetCommonObj.buildSheet($('#gljLibSheet')[0], gljOprObj.gljLibSheetSetting, gljOprObj.stdGLJ.length + gljOprObj.complementaryGLJs.length);
+            sheetCommonObj.spreadDefaultStyle(gljOprObj.gljLibSpresd);
+            gljOprObj.gljLibSpresd.bind(GC.Spread.Sheets.Events.ButtonClicked, gljOprObj.onButtonClick);
+            gljOprObj.gljLibSheet = gljOprObj.gljLibSpresd.getSheet(0);
+            gljOprObj.gljLibSheet.bind(GC.Spread.Sheets.Events.SelectionChanged, gljOprObj.onSelectionChanged);
+            gljOprObj.gljLibSheet.setColumnWidth(0, 20, GC.Spread.Sheets.SheetArea.rowHeader);
+            gljOprObj.gljLibSheet.options.isProtected = true;
+            gljOprObj.gljLibSheet.name('glj_lib');
+        }
+        gljOprObj.gljLibSheetData = gljOprObj.AllRecode;
+        let gljClass = 0, selectMap = {};
+        if ($('#actionType').val() == 'add' || $('#actionType').val() == 'insert' || $('#actionType').val() == 'insertEquipment') {//插入,添加
+            gljOprObj.GLJSelection = [];
+        } else if($('#actionType').val() =='m_replace' || $('#actionType').val() == 'replace'){//替换、批量替换
+            let selected = gljOprObj.sheetData[gljContextMenu.selectedRow];
+            let connect_key = gljOprObj.getIndex(selected, gljKeyArray);
+            gljOprObj.GLJSelection = [connect_key];
+            selectMap[connect_key] = true;
+            gljOprObj.filterLibGLJByType();
+        }else if($('#actionType').val() =='addMix'){//添加组成物
+            gljOprObj.GLJSelection = [];
+            projectGljObject.filterLibGLJForMixRatio();
+        }
+        for(let item of gljOprObj.gljLibSheetData){
+            let item_key = gljOprObj.getIndex(item, gljLibKeyArray);
+            if(selectMap[item_key]){
+                item.select = 1 ;
+                gljClass = item.gljClass;
+            }
+        }
+        //替换,焦点定位至当前选中人材机
+        if($('#actionType').val() =='m_replace' || $('#actionType').val() == 'replace'){
+            gljOprObj.locateZTree(gljClass);
+            let selected = gljOprObj.sheetData[gljContextMenu.selectedRow];
+            let index = _.findIndex(gljOprObj.gljLibSheetData, {code: selected.code});
+            gljOprObj.gljLibSheet.showRow(index, GC.Spread.Sheets.VerticalPosition.center);
+            gljOprObj.gljLibSheet.setActiveCell(index, 0);
+            gljOprObj.initSelection({row: index});
+            gljOprObj.gljLibSpresd.focus(true);
+        } else if ($('#actionType').val() === 'insertEquipment') {//右键插入设备,人材机选择窗口,应默认固定到分类"养护管理设备"。
+            let locateClass = gljOprObj.treeData.std.find(function (stdClass) {
+                return stdClass.Name === '养护管理设备';
+            });
+            if (locateClass) {
+                gljClass = locateClass.ID;
+                gljOprObj.locateZTree(gljClass);
+                gljOprObj.gljLibSheet.showRow(0, GC.Spread.Sheets.VerticalPosition.top);
+                gljOprObj.gljLibSheet.setActiveCell(0, 0);
+                gljOprObj.initSelection({row: 0});
+            }
+        } else if ($('#actionType').val() === 'add') {
+            gljOprObj.locateZTree(null);
+            gljOprObj.gljLibSheet.showRow(0, GC.Spread.Sheets.VerticalPosition.top);
+            gljOprObj.gljLibSheet.setActiveCell(0, 0);
+            gljOprObj.initSelection({row: 0});
+        } else {
+            gljOprObj.showLibGLJSheetData();
+        }
+    }
+}
+
+function initLibOptions(libData) {
+    const html = libData.reduce((acc, lib) => acc += `<option ${lib.isDefault ? 'selected="selected"' : ''} value="${lib.gljLibId}">${lib.name}</option>`, '');
+    $('#glj-lib-select').html(html);
+}
+
+function getActionUrl(actionType) {
+    const rootUrl = `/rationGlj/getGLJData/${projectObj.project.projectInfo.property.engineering_id}`
+    switch (actionType) {
+        case 'add':
+        case 'addMix':
+        case 'insertEquipment':
+            return `${rootUrl}/0/true`;
+        case 'replace':
+        case 'm_replace':
+            const selected = gljOprObj.sheetData[gljContextMenu.selectedRow];
+            const gljLibId = selected.repositoryId || commonConstants.COMPLEMENTARY_LIB;
+            return `${rootUrl}/${gljLibId}/true`;
+        case 'change': // 更改选择库
+            const selectGLJLibID = $('#glj-lib-select').val();
+            return `${rootUrl}/${selectGLJLibID}/false`;
     }
 }
 
-function getGLJData(actionType) {
+function getGLJData(actionType, isInitial = true) {
+    const url = getActionUrl(actionType);
+    if (actionType === 'change') {
+        actionType = $('#actionType').val();
+    }
     $('#actionType').val(actionType);
     $.bootstrapLoading.start();
-    projectObj.project.ration_glj.getGLJData(function (result) {
+    projectObj.project.ration_glj.getGLJData(url, function (result) {
         // 目前只有浙江2015需要特殊处理处理
         if (gljOprObj.sortSelectViewGLJ) {
             gljOprObj.sortSelectViewGLJ(result.datas.stdGLJ);
@@ -385,9 +473,6 @@ function getGLJData(actionType) {
             result.datas.stdGLJ = _.sortBy(result.datas.stdGLJ, 'code');
             result.datas.complementaryGLJs = _.sortBy(result.datas.complementaryGLJs, 'code');
         }
-        gljOprObj.treeData = result.datas.treeData;
-        //zTreeHelper.createTree(result.datas.treeData, gljOprObj.gljTreeSetting, "gljTree", gljOprObj);
-        gljOprObj.initClassTree('std', gljOprObj.treeData.std);
         gljOprObj.stdGLJ=result.datas.stdGLJ;
         gljOprObj.complementaryGLJs=result.datas.complementaryGLJs;
         for(let compleGlj of gljOprObj.complementaryGLJs){
@@ -397,20 +482,30 @@ function getGLJData(actionType) {
         gljOprObj.AllRecode=gljOprObj.stdGLJ.concat(gljOprObj.complementaryGLJs);
         //gljOprObj.AllRecode=gljOprObj.stdGLJ;
         gljOprObj.distTypeTree=gljOprObj.getComboData(result.datas.distTypeTree);
-        $('#modalCon').width($(window).width()*0.5);
-        $("input[name='glj']").get(0).checked=true;
-        $.bootstrapLoading.end();
-        if(actionType == "m_replace"){
-            $('#glj_selected_conf').hide();
-            $('#replace_next_btn').show();
-        }else {
-            $('#glj_selected_conf').show();
-            $('#replace_next_btn').hide();
+        gljOprObj.treeData = result.datas.treeData;
+        if (gljOprObj.treeData.std.length) {
+            gljOprObj.initClassTree('std', gljOprObj.treeData.std, !isInitial);
+        } else if (gljOprObj.treeData.comple.length) {
+            gljOprObj.initClassTree('comple', gljOprObj.treeData.comple, !isInitial);
         }
-        $("#glj_tree_div").modal({show:true});
-        setTimeout(function(){
-            gljOprObj.gljLibSpresd?gljOprObj.gljLibSpresd.refresh():'';
-        }, 200);
+        if (isInitial) {
+            initLibOptions(result.datas.libData);
+            $('#modalCon').width($(window).width()*0.5);
+            if(actionType == "m_replace"){
+                $('#glj_selected_conf').hide();
+                $('#replace_next_btn').show();
+            }else {
+                $('#glj_selected_conf').show();
+                $('#replace_next_btn').hide();
+            }
+            $("#glj_tree_div").modal({show:true});
+            setTimeout(function(){
+                gljOprObj.gljLibSpresd?gljOprObj.gljLibSpresd.refresh():'';
+            }, 200);
+        } else {
+            gljContextMenu.initGLJSelectView();
+        }
+        $.bootstrapLoading.end();
     })
 }
 

+ 8 - 5
web/building_saas/main/js/views/project_glj_view.js

@@ -132,6 +132,7 @@ projectGljObject={
         $("#current-name").text(me.usedUnitPriceInfo.name);
         let usedCount = me.usedTenderList.length <= 0 ? 1 : me.usedTenderList.length;
         $("#used-project-count").text(usedCount);
+        $("#editUnitFile").attr("href",`/unitPrice/index/${me.usedUnitPriceInfo.id}`)
     },
     getUsedTenderInfo:function() {
         return "人材机单价的变化,将自动影响以下单位工程造价:<br>"+projectGljObject.usedTenderList.join("<br>");
@@ -315,9 +316,11 @@ projectGljObject={
             let style = gljOprObj.getSelStyle(true,{});
             me.projectGljSheet.setStyle(newSel.row, -1, style);
             let orow = oldSel.row==''||oldSel.row==-1?0:oldSel.row;
-            let tstyle = gljOprObj.getSelStyle(false,{},me.projectGljSheetData[orow].bgColour);
-            me.projectGljSheet.setStyle(orow, -1, tstyle);
-            me.projectGljRowChang();
+            if(me.projectGljSheetData[orow]){
+              let tstyle = gljOprObj.getSelStyle(false,{},me.projectGljSheetData[orow].bgColour);
+              me.projectGljSheet.setStyle(orow, -1, tstyle);
+              me.projectGljRowChang();
+            }
         }else{
           me.projectGljSheet.repaint();
         }
@@ -881,10 +884,10 @@ projectGljObject={
         if(info.newValue === undefined ){
             return;
         }
-        if (value&&!me.checkData(col,setting,value)) {
+        if(value && !me.checkData(col,setting,value)) {
             alert('输入的数据类型不对,请重新输入!');
             info.sheetName =="materialTreeSheet"?me.materialTreeController.refreshTreeNode([me.materialTree.selected]):me.refreshProjectGljRow(row);
-            return ;
+            return;
         }
         let callback=function (impactList) {
             info.sheet.suspendPaint();

+ 18 - 8
web/building_saas/main/js/views/project_info.js

@@ -3,26 +3,36 @@
  */
 
 var projectInfoObj = {
+    getSubShareInfo: function (proj) {
+        const { allowCopy, allowCooperate } = proj.shareState;
+        let str = '(';
+        if (allowCopy) {
+            str += '可拷贝 ';
+        }
+        if (allowCooperate) {
+            if (allowCopy) {
+                str += ' ';
+            }
+            str += '可编辑';
+        }
+        str += ')';
+        return str === '()' ? '' : str;
+    },
     getFullPathHtml: function (proj) {
         let fullPath = [], i, pm = '<span class="text-truncate"><a href="/pm">项目管理</a></span>', angleRight = '<span class="text-truncate"><i class="fa fa-angle-right fa-fw"></i></span>';
         if (proj) {
             let pathArr = proj.fullPath;
             let projectName = pathArr[pathArr.length -2] || '',
                 folderName = pathArr[pathArr.length -3] || '';
+            const subShareInfo = projectInfoObj.getSubShareInfo(proj);
+            const receiveTip = `<span class="alert alert-success py-0 px-2 m-0" id="share-info"><i class="fa fa-share-alt"></i>来自 ${proj.owner && proj.owner.real_name || ''} 的分享${subShareInfo}</span>`;
             let newHtml = `   <span data-toggle="tooltip" data-placement="bottom" data-original-title="${folderName}"><i class="fa fa-folder-open-o"></i>...</span>
                 <span class="text-muted px-1">\</span>
                 <span data-toggle="tooltip" data-placement="bottom" data-original-title="${projectName}"><i class="fa fa-cubes"></i>...</span>
                 <span class="text-muted px-1">\</span>
                  <span><i class="fa fa-sticky-note-o"></i></span>
                 <span class="text-truncate"  data-toggle="tooltip" data-placement="bottom" data-original-title="${proj.name}">&nbsp;${proj.name}</span>
-                ${projectReadOnly ?
-                '<span data-toggle="tooltip" data-placement="bottom" data-original-title="当前的工程状态为“只读”,如果要进行编辑,请在项目管理-分享界面,使用“拷贝工程”功能。">(只读)</span>' 
-                : ''}
-                ${projectCooperate ? 
-                '<span data-toggle="tooltip" data-placement="bottom" data-original-title="当前的工程状态为“协作”,可直接编辑分享人的原始数据。">(协作)</span>'
-                : ''}
-                ${projectReadOnly || projectCooperate ? '' : '<span><a id="init-share" class="pl-2" href="javascript:;"><i class="fa fa-share-alt" aria-hidden="true"></i> 分享</a></span>'}
-                `;
+                ${projectReadOnly || projectCooperate ? receiveTip : `<span id="share-tip" class="ml-2" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="${proj.shareTip}"><a id="init-share" href="javascript:;" class="btn btn-xs btn-primary"><i class="fa fa-share-alt"></i> 分享</a></span>`}`;
             fullPath.push(newHtml);
 
         }

+ 169 - 0
web/building_saas/unit_price_file/index.html

@@ -0,0 +1,169 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>纵横公路养护云造价</title>
+
+
+    <link rel="stylesheet" href="/lib/jquery-ui/jquery-ui.css" type="text/css">
+    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap-submenu.css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.sc.css" type="text/css">
+    <link rel="stylesheet" href="/web/building_saas/css/main.css">
+    <link rel="stylesheet" href="/web/building_saas/css/custom.css">
+    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css" type="text/css">
+    <link rel="stylesheet" href="/lib/jquery-editable-select/jquery.editable-select.min.css" type="text/css">
+    <!--zTree-->
+    <link rel="stylesheet" href="/lib/ztree/css/zTreeStyle.css" type="text/css">
+    <!--SpreadJs-->
+   <!-- <link rel="stylesheet" href="/lib/jquery-ui/jquery-ui.css" type="text/css">
+    <link rel="stylesheet" href="/lib/spreadjs/sheets/css/gc.spread.sheets.sc.css" type="text/css">-->
+    <link rel="stylesheet" href="/lib/spreadjs/views/gc.spread.views.dataview.10.0.0.css">
+    <!-- jquery.contextmenu -->
+   <!-- <link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css" type="text/css">-->
+
+    <link rel="shortcut icon" href="/web/building_saas/css/favicon.ico">
+    <link rel="icon" type="image/gif" href="/web/building_saas/css/animated_favicon1.gif">
+    <style type="text/css">
+        .ztree * {
+            font-family: Calibri;
+            font-size: 0.9rem;
+        }
+    </style>
+
+</head>
+<script type="text/javascript">
+  let unitPriceList = JSON.parse(`<%- unitpriceList %>`);
+  let gljTypeMap = JSON.parse(`<%- gljTypeMap %>`);
+  let mixRatioMap = JSON.parse(`<%- mixRatioMap %>`);
+</script>
+<body oncontextmenu="return false;">  <!--屏蔽input鼠标右键-->
+<!--<div id="toolToastWrap" style="left: 20px; right: 30px; position: fixed; z-index: 10001; top: 100px;">
+    <div id="toolToast" class="toolToast">
+        <span id="tool-toast-content">右键不支持粘贴外部内容,请使用Ctrl+V粘贴。<span id="toolToastBtn">我知道了</span></span>
+    </div>
+</div>-->
+
+    <div class="header">
+         <div class="top-msg clearfix">
+            <div class="alert alert-warning alert-dismissible" role="alert" id="notify" style="display: none">
+                <button type="button" class="close" aria-label="Close" onclick="$('#notify').hide();">
+                  <span aria-hidden="true">&times;</span>
+                </button>
+                <strong id="message"></strong>-
+            </div>
+        </div>
+        <nav class="navbar navbar-expand-lg p-0 d-flex <%= versionName.includes('免费') ? 'free-version' : 'pro-version' %>">
+          <div class="unit_price_header header-logo ">
+            <h5>单价文件编辑器</h5>
+          </div>
+          <div class="navbar-text navbar-crumb px-1 mr-auto" id="fullpath">   
+            <span class="text-muted px-1"></span>
+            <span data-toggle="tooltip" data-placement="bottom" data-original-title="<%= rootProjectName%>"><i class="fa fa-cubes"></i>...</span>
+            <span class="text-muted px-1"></span>
+             <span><i class="fa fa-puzzle-piece"></i></span>
+            <span class="text-truncate" data-toggle="tooltip" data-placement="bottom" data-original-title="<%= unitFileName%>">&nbsp;<%= unitFileName%></span>
+            &nbsp;(<span class="a_color" data-toggle="tooltip" id="pop-used-list"  style="float: none;" data-original-title="" title="<%= usedTenderString%>">与<span id="used-project-count" style="float: none;">1</span>个单位工程同步</span>)
+          </div>
+        </nav>
+    </div>
+    <div class="main">
+        <div class="content" style="margin-left: 0px;">
+          <div class="tab-content">
+              <!--造价书-->
+              <div class="container-fluid">
+                  <div class="row" id="mainRow">
+                      <!--col-lg-12 p-0-->
+                      <div class="main-content" style="width: 100%; display: inline-block" id="main">
+                          <div class="top-content" id="top_div" style="overflow:hidden;">
+                              <div class="main-data-top" id="mainSpread"></div>
+                          </div>
+                          <div class="resize-y" id="mainVerticalResize"></div>
+                          <div class="bottom-content" id="bottom_div">
+                              <ul class="nav nav-tabs" role="tablist" id="bottom_div_ul">  
+                                  <li class="nav-item" id="GLJ_div">
+                                      <a class="nav-link sub-item active" id="linkGLJ" data-toggle="tab" href="#subSpread" role="tab">组成物计算</a>
+                                  </li>                                
+                              </ul>
+                              <!-- Tab panes -->
+                              <div class="tab-content" id="tabCon">
+                                  <div class="tab-pane active" id="subItems" role="tabpanel">
+                                     <div class="main-data-bottom ovf-hidden" id="subSpread" tabindex="0"></div>
+                                  </div>
+                              </div>
+                          </div>
+                      </div>
+                      </div>
+                  </div>
+              </div>
+            </div>
+
+
+        </div>
+    </div>
+   
+
+   
+ 
+   
+    <img src="/web/dest/css/img/folder_open.png" id="folder_open_pic" style="display: none">
+    <img src="/web/dest/css/img/folder_close.png" id="folder_close_pic" style="display: none">
+    <img src="/web/dest/css/img/project.png" id="proj_pic" style="display: none">
+    <img src="/web/dest/css/img/engineering.png" id="eng_pic" style="display: none">
+    <img src="/web/dest/css/img/tender.png" id="tender_pic" style="display: none">
+
+    <img src="/web/dest/css/img/blockLib.png" id="blockLib_pic" style="display: none">
+    <img src="/web/dest/css/img/folder_open.png" id="folder_pic" style="display: none">
+    <img src="/web/dest/css/img/tender.png" id="block_pic" style="display: none">
+
+        <!-- JS. -->
+    <script src="/lib/jquery/jquery-3.2.1.min.js"></script>
+    <script type="text/javascript" src="/lib/jquery-ui/jquery-ui.min.js"></script>
+    <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js"></script>
+    <script src="/lib/spreadjs/sheets/interop/gc.spread.excelio.11.1.2.min.js"></script>
+    <script>GC.Spread.Sheets.LicenseKey =  '<%- LicenseKey %>';</script>
+    <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 src="/lib/spreadjs/views/gc.spread.views.dataview.10.0.0.min.js" type="text/javascript"></script>
+    <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
+    <script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>
+    <!--<script src="/lib/spreadjs/views/common/gc.spread.common.10.0.0.min.js" type="text/javascript"></script>-->
+    <script src="/lib/spreadjs/views/plugins/gc.spread.views.gridlayout.10.0.0.min.js" type="text/javascript"></script>
+    <script src="/lib/js-xlsx/xlsx.core.min.js"></script>
+    <script src="/lib/lz-string/lz-string.min.js"></script>
+    <script type="text/javascript" src="/lib/jspdf/jspdf.min.js"></script>
+    <!-- inject:js -->
+    <script src="/lib/popper/popper.min.js"></script>
+    <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/lib/bootstrap/bootstrap-submenu.js"></script>
+    <script type="text/javascript" src="/web/building_saas/js/moment.min.js"></script>
+    <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/gljUtil.js"></script>
+    <script type="text/javascript" src="/public/web/PerfectLoad.js"></script>
+    <script type="text/javascript" src="/lib/lodash/lodash.js"></script>
+    <script type="text/javascript" src="/public/web/commonAlert.js"></script>
+    <script type="text/javascript" src="/public/web/headerOpr.js"></script>
+    <script type="text/javascript" src="/public/web/common_ajax.js"></script>
+    <script type="text/javascript" src="/public/common_util.js"></script>
+    <script src="/public/common_constants.js"></script>
+    <script type="text/javascript" src="/lib/jquery-editable-select/jquery.editable-select.min.js"></script>
+    <script type="text/javascript" src="/public/web/tree_sheet/tree_sheet_helper.js"></script>
+    <script type="text/javascript" src="/public/web/sheet/sheet_data_helper.js"></script>
+    <script type="text/javascript" src="/public/web/sheet/sheet_common.js"></script>
+
+
+
+    <script type="text/javascript" src="/web/building_saas/unit_price_file/index.js"></script>
+    <!-- endinject -->
+
+
+        
+   
+</body>
+</html>

+ 293 - 0
web/building_saas/unit_price_file/index.js

@@ -0,0 +1,293 @@
+
+let unitPriceObj = {
+  unitPriceMap:{},
+  setUntiPriceMap:function(){
+    for(let u of unitPriceList){
+      this.unitPriceMap[gljUtil.getIndex(u)] = u;
+    }
+  },
+  mainSpread:null,
+  mainSetting:{
+    header: [
+        {headerName: "编号", headerWidth: 80, dataCode: "code", dataType: "String"},
+        {headerName: "名称", headerWidth: 160, dataCode: "name", dataType: "String"},
+        {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+        {headerName: "规格", headerWidth: 120, dataCode: "specs", hAlign: "left", dataType: "String"},
+        {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String"},
+        {headerName: "定额价", headerWidth: 70, dataCode: "basePrice", hAlign: "right", dataType: "Number",validator:"number"},//decimalField:'glj.unitPrice',
+        {headerName: "预算价", headerWidth: 70, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
+        {headerName: "是否新增", headerWidth: 50, dataCode: "is_add", hAlign: "center", dataType: "String",cellType:'checkBox'}
+    ],
+    view: {
+        lockColumns: ["code","name","specs","unit","short_name","basePrice","is_add"],
+        colHeaderHeight:36
+    },
+    getStyle:function (data,row,activeRow) {
+      if(row == activeRow){//选中黄色显示
+          return {backColor:"#FFFACD"};
+      }
+      return null;
+    }
+  },
+  subSpread:null,
+  subSetting:{
+    header:[
+        {headerName: "编号", headerWidth: 80, dataCode: "code", dataType: "String"},
+        {headerName: "名称", headerWidth: 240, dataCode: "name", dataType: "String"},
+        {headerName: "规格", headerWidth: 190, dataCode: "specs", dataType: "String"},
+        {headerName: "单位", headerWidth: 45, dataCode: "unit", hAlign: "center", dataType: "String"},
+        {headerName: "类型", headerWidth: 45, dataCode: "short_name", hAlign: "center", dataType: "String"},
+        {headerName: "定额价", headerWidth: 80, dataCode: "basePrice", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:'glj.unitPrice'
+        {headerName: "预算价", headerWidth: 80, dataCode: "marketPrice", hAlign: "right", dataType: "Number",validator:"number"},//,decimalField:"glj.unitPrice"
+        {headerName: "消耗量", headerWidth: 80, dataCode: "consumption", hAlign: "right", dataType: "Number",validator:"number",tofix:3}
+    ],
+    view: {
+        lockColumns: [0,1,2,3,4,5,6,7],
+        rowHeaderWidth: 25
+    }
+  },
+  initMainSpread:function () {
+    if(this.mainSpread) return this.mainSpread.refresh();
+    this.mainSpread = SheetDataHelper.createNewSpread($("#mainSpread")[0]);
+    sheetCommonObj.spreadDefaultStyle(this.mainSpread);
+    this.mainSheet = this.mainSpread.getSheet(0);
+    sheetCommonObj.initSheet(this.mainSheet, this.mainSetting, 30);
+    this.mainSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onMainSelectionChange);
+    this.mainSpread.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMainRangeChange);
+    this.mainSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onMainValueChange);
+    // this.sheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onElectrovalenceEditStarting);
+
+    /* if(projectReadOnly){
+        disableSpread(this.spread);
+    } */
+  },
+  showMainDatas:function(){
+    unitPriceList = gljUtil.sortProjectGLJ(unitPriceList);
+    this.setData(unitPriceList);
+    let sel = this.mainSheet.getSelections()[0];
+    let oldData = sel.row<unitPriceList.length?unitPriceList[sel.row]:"";
+    sheetCommonObj.showData(this.mainSheet, this.mainSetting,unitPriceList);
+    this.mainSheet.setRowCount(unitPriceList.length);
+    sel.row =  oldData?_.findIndex(unitPriceList,{'id':oldData.id}):sel.row ;
+    this.mainSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
+  
+  },
+  getShortNameByType : function (type) {
+    return gljTypeMap["typeId" + type]?gljTypeMap["typeId" + type].shortName:'';
+  },
+  setData:function(list){
+    for(let l of list){
+      l.bgColour = "white";
+      l.basePrice = this.getPrice('base_price',l);
+      l.marketPrice = this.getPrice('market_price',l);
+      l.short_name = this.getShortNameByType(l.type);
+      if(l.base_price == l.market_price){//如果定额价等于市场价时,改底色。 优先度低于有组成物时的底色
+        l.bgColour = "#C4CAFB";
+      }
+      let lindex = gljUtil.getIndex(l);
+      if (gljUtil.notEditType.indexOf(l.type) >= 0 && mixRatioMap[lindex] && mixRatioMap[lindex].length>0) {//有组成物时
+        l.bgColour = "#E0E0E0";
+      }
+      if(gljUtil.isConcreteType(l.type)) l.bgColour = "#E0E0E0";//混凝土、砂浆、配合比的底色显示为 灰色#E0E0E0,灰色底色提醒用户不可修改。
+
+    }
+  },
+  getSelectedUnitPrice:function () {
+    let me = this,data = null;
+    let sheet = me.mainSpread.getActiveSheet();
+    let sel = sheet.getSelections()[0];
+        let srow = sel.row == -1||sel.row == ""?0:sel.row;
+        if(unitPriceList.length>srow){
+            data = unitPriceList[srow];
+        }
+    return data;
+  },
+  onMainSelectionChange:function(sender,args){
+    let me = unitPriceObj;
+    let newSel = args.newSelections[0];
+    let oldSel = args.oldSelections?args.oldSelections[0]:{};
+    args.sheet.suspendPaint();
+    args.sheet.suspendEvent();
+    if(newSel.row != oldSel.row){
+      let style = me.getSelStyle(true,{});
+      args.sheet.setStyle(newSel.row, -1, style);
+      let orow = oldSel.row==''||oldSel.row==-1?0:oldSel.row;
+      if(unitPriceList[orow]){
+        let tstyle = me.getSelStyle(false,{},unitPriceList[orow].bgColour);
+        args.sheet.setStyle(orow, -1, tstyle);
+        me.showSubDatas();
+      }
+    }else{
+      args.sheet.repaint();
+    }
+    args.sheet.resumeEvent();
+    args.sheet.resumePaint();
+
+  },
+  onMainValueChange:function(e,info){
+    let me = unitPriceObj;
+    let value = info.newValue;
+    if(info.newValue === undefined){
+      return;
+    }
+    if(value && !sheetCommonObj.checkData(info.col,me.mainSetting,value)) {
+      alert('输入的数据类型不对,请重新输入!');
+      return me.showMainDatas();
+    }
+    me.batchUpdateUnitPrice([{row:info.row,col:info.col,value:value}]);
+
+  },
+  onMainRangeChange:function(sender,info){
+    let me = unitPriceObj;
+    let canChange = true;
+    for(let c of info.changedCells){
+      let value=  info.sheet.getCell(c.row, c.col).text();
+      changeInfo.push({row:c.row,col:c.col,value:value});
+      if (!sheetCommonObj.checkData(c.col,me.mainSetting,value)) {
+          alert('输入的数据类型不对,请重新输入!');
+          canChange = false;
+          break;
+      }
+    }
+    if(canChange == false) return me.showMainDatas();
+    me.batchUpdateUnitPrice(changeInfo);
+  },
+  batchUpdateUnitPrice:async function(changeInfo){
+    let me = unitPriceObj;
+    let updateData = [];
+    let newValueMap = {};
+    let refreshList = [];
+    try {
+      for(let ci of changeInfo){
+        let dataCode = me.mainSetting.header[ci.col].dataCode;
+        let recode = unitPriceList[ci.row];
+        if(dataCode=='basePrice'||dataCode=='marketPrice'){
+            let editField = dataCode === 'basePrice'?"base_price":"market_price";
+            let newValue = ci.value;
+            if(recode && recode[editField]!=newValue){
+                newValue= scMathUtil.roundForObj(ci.value,3);
+                updateData.push({unit_price: recode, field: editField, newval: newValue});
+                newValueMap[recode.id]={field:editField,value:newValue};
+                refreshList.push(recode);
+            }
+        }
+      }
+      if(updateData.length > 0){
+        $.bootstrapLoading.start();
+        let result = await ajaxPost("/glj/batchUpdatePrices",updateData);
+        for(let r of refreshList){
+           r[newValueMap[r.id].field] = newValueMap[r.id].value;
+        }
+        for(let r of result){
+          let pdata = r.updateOne.filter;
+          let set = r.updateOne.update.$set;
+          for(let skey in set){
+              let pindex = gljUtil.getIndex(pdata);
+              me.unitPriceMap[pindex][skey] = set[skey];
+          }
+        }
+      }
+    } catch (error) {
+        alert(error);
+    }
+    $.bootstrapLoading.end();
+    me.showMainDatas();
+
+  },
+
+  initSubSpread:function () {
+    if(this.subSpread) return this.subSpread.refresh();
+    this.subSpread = SheetDataHelper.createNewSpread($("#subSpread")[0]);
+    sheetCommonObj.spreadDefaultStyle(this.subSpread);
+    this.subSheet = this.subSpread.getSheet(0);
+    sheetCommonObj.initSheet(this.subSheet, this.subSetting, 30);
+    // this.sheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onElectrovalenceSelectionChange);
+    // this.sheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onElectrovalenceValueChange);
+    // this.sheet.bind(GC.Spread.Sheets.Events.EditStarting,this.onElectrovalenceEditStarting);
+
+    /* if(projectReadOnly){
+        disableSpread(this.spread);
+    } */
+  },
+  showSubDatas:function(){
+    let parentData = this.getSelectedUnitPrice();
+    this.mixRatioList = mixRatioMap[gljUtil.getIndex(parentData)];
+    this.mixRatioList = this.mixRatioList?this.mixRatioList:[];
+    this.setMixRatioData(this.mixRatioList);
+    let sel = this.subSheet.getSelections()[0];
+    this.subSheet.setRowCount(0);
+    sheetCommonObj.showData(this.subSheet, this.subSetting,this.mixRatioList);
+    this.subSheet.setRowCount(this.mixRatioList.length);
+    this.subSheet.setSelection(sel.row==-1?0:sel.row,sel.col,sel.rowCount,sel.colCount);
+  },
+  setMixRatioData:function(mixRatioList){
+    for(let m of mixRatioList){
+      m.short_name = this.getShortNameByType(m.type);
+      let mu = this.unitPriceMap[gljUtil.getIndex(m)];
+      if(mu){
+        m.basePrice = this.getPrice("base_price",mu);
+        m.marketPrice = this.getPrice("market_price",mu);
+      }else{
+        console.log("组成物的单价信息未找到---"+m.code);
+      }
+    }
+  },
+  getPrice:function(pricefield,unitprice){
+    let quantity = 3;
+    let unitPriceHasMix = 2;
+    let unitPrice = 3;
+    let process_decimal = 6;
+    let uIndex = gljUtil.getIndex(unitprice);
+    if(mixRatioMap[uIndex] && mixRatioMap[uIndex].length > 0){
+      let total = unitprice[pricefield];
+      if(pricefield == "market_price"){
+        total = 0;
+        for(let m of mixRatioMap[uIndex]){
+          let mu = unitPriceObj.unitPriceMap[gljUtil.getIndex(m)];
+          let price_m =  unitPriceObj.getPrice(pricefield,mu);
+          let temP = scMathUtil.roundForObj(price_m * scMathUtil.roundForObj(m.consumption,quantity),process_decimal);
+          total = scMathUtil.roundForObj(temP+total,process_decimal);
+        }
+      }
+      return scMathUtil.roundForObj(unitprice[pricefield],unitPriceHasMix);
+    }else{
+      return scMathUtil.roundForObj(unitprice[pricefield],unitPrice);
+    }
+  },
+  getSelStyle: function (selected,settingStyle,rcolor) {
+    let style = new GC.Spread.Sheets.Style();
+    if(settingStyle){
+        for(let key in settingStyle){
+            style[key] = settingStyle[key];
+        }
+    }
+    style.borderLeft = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    style.borderTop = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    style.borderRight = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    style.borderBottom = new GC.Spread.Sheets.LineBorder("#D4D4D4", GC.Spread.Sheets.LineStyle.thin);
+    let selectedColor = "#FFFACD",
+        recColor = rcolor?rcolor:'White';
+    style.backColor = selected ? selectedColor : recColor;
+    return style;
+  },
+}
+
+
+
+function initPageHeight(){
+  let headerHeight = $(".header").height();
+  $(".main-data-top").height($(window).height()*0.6-headerHeight);
+  $(".main-data-bottom").height($(window).height()-headerHeight-$(".main-data-top").height()-$(".nav-item").height());
+}
+function initPage(){
+  $('[data-toggle="tooltip"]').tooltip({html: true});
+  initPageHeight();
+  unitPriceObj.initMainSpread();
+  unitPriceObj.initSubSpread();
+  unitPriceObj.showMainDatas();
+}
+
+unitPriceObj.setUntiPriceMap();
+initPage();
+$(window).resize(initPage);
+

+ 25 - 0
web/common/components/share/index.js

@@ -261,6 +261,7 @@ const SHARE_TO = (() => {
                     initContactsView(rst.contacts)
                 }
                 initSharedView(curSharedUsers);
+                refreshShareTip(curSharedUsers);
                 refreshTreeView();
             }
         } catch (err) {
@@ -285,6 +286,30 @@ const SHARE_TO = (() => {
         }
     }
 
+    // 刷新造价书的分享按钮tooltip提示
+    function refreshShareTip(sharedUsers) {
+        const $shareTip = $('#share-tip');
+        if (!$shareTip) {
+            return;
+        }
+        const limit = 2;
+        const count = sharedUsers.length;
+        const users = sharedUsers.slice(0, 2);
+        const tip = users.reduce((acc, user, index) => {
+            if (index === 0) {
+                acc += '已分享给';
+                acc += user.real_name;
+            } else {
+                acc += ` ${user.real_name}`;
+            }
+            if (index === users.length - 1 && count > limit) {
+                acc += `等${count}人`;
+            }
+            return acc;
+        }, '');
+        $shareTip.attr('data-original-title', tip);
+    }
+
     // 初始化分享给的页面
     async function initModal(projectID) {
         try {

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

@@ -3,7 +3,7 @@
     <% if(controller === 'boot' || controller === 'pm'){ %>
     <!--<a style="text-decoration: none" href="javascript:void(0);" class="header-logo">-->
     <% }else { %>
-    <div class="mx-2"><a href="/pm" class="btn btn-sm text-white" data-toggle="tooltip" title="返回项目管理"><i class="fa fa-angle-left" style="font-size:24px"></i></a></div>
+    <div class="mx-2"><a href="/pm" class="btn btn-sm" data-toggle="tooltip" title="返回项目管理"><i class="fa fa-angle-left" style="font-size:24px"></i></a></div>
         <!--<a style="text-decoration: none" href="/pm" class="header-logo">-->
     <% } %>
     <div class="header-logo">