Procházet zdrojové kódy

Merge branch '1.0.0_online' of http://192.168.1.12:3000/SmartCost/ConstructionCost into 1.0.0_online

TonyKang před 6 roky
rodič
revize
d33a760cc2
69 změnil soubory, kde provedl 2559 přidání a 657 odebrání
  1. 2 0
      config/gulpConfig.js
  2. 53 0
      modules/all_models/material_replace_lib.js
  3. 1 1
      modules/bills_lib/models/bills_lib_interfaces.js
  4. 29 28
      modules/common/const/glj_type_const.js
  5. 1 1
      modules/complementary_ration_lib/models/compleRationModel.js
  6. 69 0
      modules/complementary_ration_lib/models/searchModel.js
  7. 1 1
      modules/fee_rates/facade/fee_rates_facade.js
  8. 1 1
      modules/glj/models/glj_list_model.js
  9. 34 0
      modules/main/controllers/material_replace_controller.js
  10. 1 2
      modules/main/controllers/project_controller.js
  11. 42 75
      modules/main/controllers/ration_controller.js
  12. 3 1
      modules/main/facade/bill_facade.js
  13. 122 0
      modules/main/facade/material_replace_facade.js
  14. 50 27
      modules/main/facade/ration_facade.js
  15. 16 0
      modules/main/routes/material_replace_route.js
  16. 4 4
      modules/main/routes/ration_route.js
  17. 16 1
      modules/pm/controllers/pm_controller.js
  18. 32 0
      modules/pm/models/project_model.js
  19. 1 0
      modules/pm/routes/pm_route.js
  20. 18 4
      modules/ration_glj/facade/glj_calculate_facade.js
  21. 14 7
      modules/ration_glj/facade/ration_glj_facade.js
  22. 3 3
      modules/std_billsGuidance_lib/facade/facades.js
  23. 5 1
      modules/users/controllers/boot_controller.js
  24. 4 0
      modules/users/controllers/login_controller.js
  25. 49 4
      modules/users/controllers/user_controller.js
  26. 21 0
      modules/users/models/user_model.js
  27. 1 0
      modules/users/routes/user_route.js
  28. 13 0
      public/web/sheet/sheet_common.js
  29. 10 2
      public/web/sheet/sheet_data_helper.js
  30. 37 20
      public/web/tree_sheet/tree_sheet_helper.js
  31. 1 1
      web/building_saas/complementary_glj_lib/html/tools-gongliaoji.html
  32. 151 96
      web/building_saas/complementary_glj_lib/js/glj.js
  33. 1 1
      web/building_saas/complementary_ration_lib/html/dinge.html
  34. 32 26
      web/building_saas/complementary_ration_lib/js/ration.js
  35. 46 0
      web/building_saas/css/custom.css
  36. 77 18
      web/building_saas/css/main.css
  37. 1 1
      web/building_saas/glj/html/project_glj.html
  38. 49 7
      web/building_saas/main/html/main.html
  39. 0 1
      web/building_saas/main/js/controllers/block_controller.js
  40. 154 0
      web/building_saas/main/js/controllers/material_controller.js
  41. 8 5
      web/building_saas/main/js/controllers/project_controller.js
  42. 8 0
      web/building_saas/main/js/main.js
  43. 15 2
      web/building_saas/main/js/models/calc_base.js
  44. 21 12
      web/building_saas/main/js/models/calc_program.js
  45. 3 3
      web/building_saas/main/js/models/ration.js
  46. 20 19
      web/building_saas/main/js/models/ration_glj.js
  47. 186 0
      web/building_saas/main/js/views/block_lib.js
  48. 56 6
      web/building_saas/main/js/views/calc_base_view.js
  49. 1 0
      web/building_saas/main/js/views/confirm_modal.js
  50. 20 11
      web/building_saas/main/js/views/fee_rate_view.js
  51. 12 5
      web/building_saas/main/js/views/glj_view.js
  52. 1 0
      web/building_saas/main/js/views/importBills.js
  53. 2 2
      web/building_saas/main/js/views/main_tree_col.js
  54. 18 16
      web/building_saas/main/js/views/project_glj_view.js
  55. 156 36
      web/building_saas/main/js/views/project_view.js
  56. 45 5
      web/building_saas/main/js/views/quantity_edit_view.js
  57. 132 56
      web/building_saas/main/js/views/std_billsGuidance_lib.js
  58. 12 9
      web/building_saas/main/js/views/std_bills_lib.js
  59. 94 22
      web/building_saas/main/js/views/std_ration_lib.js
  60. 54 68
      web/building_saas/main/js/views/zmhs_view.js
  61. 133 5
      web/building_saas/pm/html/project-management.html
  62. 30 6
      web/building_saas/pm/js/pm_newMain.js
  63. 6 2
      web/common/html/header.html
  64. 55 29
      web/over_write/js/chongqing_2018.js
  65. 302 0
      web/users/html/user-buy.html
  66. 1 1
      web/users/html/user-info.html
  67. 1 1
      web/users/html/user-safe.html
  68. 1 1
      web/users/html/user-set.html
  69. 1 1
      web/users/js/user.js

+ 2 - 0
config/gulpConfig.js

@@ -119,10 +119,12 @@ module.exports = {
         'web/building_saas/main/js/main.js',
         'web/building_saas/main/js/controllers/project_controller.js',
         'web/building_saas/main/js/controllers/block_controller.js',
+        'web/building_saas/main/js/controllers/material_controller.js',
         'web/building_saas/main/js/views/side_tools.js',
         'web/building_saas/main/js/views/std_billsGuidance_lib.js',
         'web/building_saas/main/js/views/std_bills_lib.js',
         'web/building_saas/main/js/views/std_ration_lib.js',
+        'web/building_saas/main/js/views/block_lib.js',
         'web/building_saas/main/js/models/quantity_detail.js',
         'web/building_saas/main/js/views/glj_view_contextMenu.js',
         'web/building_saas/main/js/views/calc_program_view.js',

+ 53 - 0
modules/all_models/material_replace_lib.js

@@ -0,0 +1,53 @@
+/**
+ * Created by zhang on 2018/8/22.
+ */
+//材料替换库
+const mongoose = require('mongoose');
+const Schema = mongoose.Schema;
+const oprSchema = require('../all_schemas/opr_schema');
+const material_lib = new Schema({
+        ID:{type:String,index:true},
+        creator: String,
+        createDate: Number,
+        recentOpr: [oprSchema],
+        name: String,
+        compilationId: String,
+        compilationName: String,
+        billsLibId:Number,
+        billsLibName:String,
+        deleted: Boolean
+    }, {versionKey: false}
+);
+
+mongoose.model("std_material_replace_lib", material_lib,"std_material_replace_lib");
+
+
+const std_replace_bills = new Schema({
+        ID: {type:String,index:true},
+        libID:{type:String,index:true},
+        code: {type:String,index:true},
+        name: String,
+        rule:Number//规则类型
+    }, {versionKey: false}
+);
+
+mongoose.model('std_replace_bills', std_replace_bills, 'std_replace_bills');
+
+
+const std_replace_material = new Schema({
+    ID: {type:String,index:true},
+    libID:{type:String,index:true},
+    billsItemID:{type:String,index:true},
+    code: String,
+    name: String,
+    specs: String,
+    type: Number,
+    unit: String
+},{versionKey: false});
+
+mongoose.model('std_replace_material', std_replace_material, 'std_replace_material');
+
+
+
+
+

+ 1 - 1
modules/bills_lib/models/bills_lib_interfaces.js

@@ -225,7 +225,7 @@ billsLibDao.prototype.getCurrentUniqId = function(callback){
 }
 //----------------------------Bills---------------------
 billsLibDao.prototype.getBills = function (billsLibId, callback) {
-    Bills.find({billsLibId: billsLibId, deleted: false}, "-_id",  function(err, billsData){
+    Bills.find({billsLibId: billsLibId}, "-_id -ruleText -recharge",  function(err, billsData){
         if(err){
             callback(1, "Error", null);
         }

+ 29 - 28
modules/common/const/glj_type_const.js

@@ -7,34 +7,35 @@
  */
 
 const gljType = {
-    // 人工
-    LABOUR: 1,
-    // ==============材料类型=================
-    // 普通材料
-    GENERAL_MATERIAL: 201,
-    // 混凝土
-    CONCRETE: 202,
-    // 砂浆
-    MORTAR: 203,
-    // 配合比
-    MIX_RATIO: 204,
-    // 商品混凝土
-    COMMERCIAL_CONCRETE: 205,
-    // 商品砂浆
-    COMMERCIAL_MORTAR: 206,
-    // ==============材料类型=================
-    // ==============机械类型=================
-    // 普通机械
-    GENERAL_MACHINE: 301,
-    // 机械组成物
-    MACHINE_COMPOSITION: 302,
-    // 机上人工
-    MACHINE_LABOUR: 303,
-    // ==============机械类型=================
-    // 主材
-    MAIN_MATERIAL: 4,
-    // 设备
-    EQUIPMENT: 5
+    LABOUR: 1,                                  // 人工
+    // ==============材料类型 ↓=================
+    GENERAL_MATERIAL: 201,                      // 普通材料
+    CONCRETE: 202,                              // 混凝土
+    MORTAR: 203,                                // 砂浆
+    MIX_RATIO: 204,                             // 配合比
+    COMMERCIAL_CONCRETE: 205,                   // 商品混凝土
+    COMMERCIAL_MORTAR: 206,                     // 商品砂浆
+    OTHER_MATERIAL: 207,                        // 其它材料
+    // ==============材料类型 ↑=================
+    // ==============机械类型 ↓=================
+    GENERAL_MACHINE: 301,                       // 机械台班
+    MACHINE_COMPOSITION: 302,                   // 机械组成物
+    MACHINE_LABOUR: 303,                        // 机上人工
+    INSTRUMENT: 304,                            // 仪器仪表
+    FUEL_POWER_FEE:305,                         // 燃料动力费
+    DEPRECIATION_FEE:306,                       // 折旧费
+    INSPECTION_FEE:307,                         // 检修费
+    MAINTENANCE:308,                            // 维护费
+    DISMANTLING_FREIGHT_FEE:309,                // 安拆费及场外运费
+    VERIFICATION_FEE:310,                       // 校验费
+    OTHER_FEE:311,                              // 其他费用
+    OTHER_MACHINE_USED:312,                     // 其他施工机具使用费
+    // ==============机械类型 ↑=================
+    MAIN_MATERIAL: 4,                           // 主材
+    EQUIPMENT: 5,                               // 设备
+    MANAGEMENT_FEE: 6,                          // 企业管理费
+    PROFIT: 7,                                  // 利润
+    GENERAL_RISK_FEE: 8                         // 一般风险费
 };
 
 export default gljType;

+ 1 - 1
modules/complementary_ration_lib/models/compleRationModel.js

@@ -172,7 +172,7 @@ class CompleRatoinDao {
                          glj = await complementaryGljModel.findOne({uesrId: userId, ID: rationGlj.gljId});
                     }
                     if(isDef(glj)){
-                        hintsArr.push(` ${glj.code} ${glj.name} ${glj.unit} ${rationGlj.consumeAmt}`);
+                        hintsArr.push(` ${glj.code} ${glj.name}${glj.specs ? ' ' + glj.specs : ''} ${glj.unit} ${rationGlj.consumeAmt}`);
                     }
                 }
                 hintsArr.push(`基价 元 ${ration.basePrice}`);

+ 69 - 0
modules/complementary_ration_lib/models/searchModel.js

@@ -69,15 +69,84 @@ class SearchDao{
                     '$or': [{'isDeleted': {"$exists":false}}, {'isDeleted': null}, {'isDeleted': false}, {deleteInfo: null}]
                 }]
             };
+            let stdGljIds = [],
+                comGljIds = [];
             let stdRations = await stdRationModel.find(filter);
             for(let i = 0, len = stdRations.length; i < len; i++){
                 stdRations[i]._doc.type = 'std';
+                for(let glj of stdRations[i].rationGljList){
+                    stdGljIds.push(glj.gljId);
+                }
             }
             filter.userId = userId;
             let compleRations = await compleRationModel.find(filter);
             for(let i = 0, len = compleRations.length; i <len; i++){
                 compleRations[i]._doc.type = 'complementary';
+                for(let glj of stdRations[i].rationGljList){
+                    if(glj.type === 'std'){
+                        stdGljIds.push(glj.gljId);
+                    }
+                    else {
+                        comGljIds.push(glj.gljId);
+                    }
+                }
+            }
+            //设置悬浮信息
+            stdGljIds = Array.from(new Set(stdGljIds));
+            comGljIds = Array.from(new Set(comGljIds));
+            let gljIDMapping = {};
+            if(stdGljIds.length > 0){
+                let stdGljs = await stdGljModel.find({ID: {$in: stdGljIds}}, '-_id ID code name specs unit');
+                for(let stdGlj of stdGljs){
+                    gljIDMapping[stdGlj.ID] = stdGlj;
+                }
+            }
+            if(comGljIds.length > 0){
+                let comGljs = await complementaryGljModel.find({ID: {$in: stdGljIds}});
+                for(let comGlj of comGljs){
+                    gljIDMapping[comGlj.ID] = comGlj;
+                }
+            }
+            for(let ration of stdRations){
+                let hintsArr = [];
+                for(let rationGlj of ration.rationGljList){
+                    let glj = gljIDMapping[rationGlj.gljId];
+                    if(glj){
+                        hintsArr.push(` ${glj.code} ${glj.name}${glj.specs ? ' ' + glj.specs : ''} ${glj.unit} ${rationGlj.consumeAmt}`);
+                    }
+                }
+                hintsArr.push(`基价 元 ${ration.basePrice}`);
+                if(ration.jobContent && ration.jobContent.toString().trim() !== ''){
+                    hintsArr.push(`工作内容:`);
+                    hintsArr = hintsArr.concat(ration.jobContent.split('\n'));
+                }
+                if(ration.annotation && ration.annotation.toString().trim() !== ''){
+                    hintsArr.push(`附注:`);
+                    hintsArr = hintsArr.concat(ration.annotation.split('\n'));
+                }
+                ration._doc.hint = hintsArr.join('<br>');
+            }
+            for(let ration of compleRations){
+                let hintsArr = [];
+                for(let rationGlj of ration.rationGljList){
+                    let glj = gljIDMapping[rationGlj.gljId];
+                    if(glj){
+                        hintsArr.push(` ${glj.code} ${glj.name}${glj.specs ? ' ' + glj.specs : ''} ${glj.unit} ${rationGlj.consumeAmt}`);
+                    }
+                }
+                hintsArr.push(`基价 元 ${ration.basePrice}`);
+                if(ration.jobContent && ration.jobContent.toString().trim() !== ''){
+                    hintsArr.push(`工作内容:`);
+                    hintsArr = hintsArr.concat(ration.jobContent.split('\n'));
+                }
+                if(ration.annotation && ration.annotation.toString().trim() !== ''){
+                    hintsArr.push(`附注:`);
+                    hintsArr = hintsArr.concat(ration.annotation.split('\n'));
+                }
+                ration._doc.hint = hintsArr.join('<br>');
             }
+
+
             callback(0, stdRations.concat(compleRations));
         }
         catch(err){

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

@@ -283,7 +283,7 @@ async function newFeeRateFile(userId, updateData){
                 newFeeRate.name = temFee.name;
                 return newFeeRate;
             }
-            let temA = feeFile.id.split("-");
+            let temA = feeFile.id.split("@@");
             let libID = temA[1];
             let doc={
                 userID: userId,

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

@@ -38,7 +38,7 @@ class GLJListModel extends BaseModel {
      * @var {Array}
      */
     ownCompositionTypes = [GLJTypeConst.CONCRETE, GLJTypeConst.MORTAR, GLJTypeConst.MIX_RATIO,
-        GLJTypeConst.GENERAL_MACHINE,GLJTypeConst.MAIN_MATERIAL];
+        GLJTypeConst.GENERAL_MACHINE,GLJTypeConst.MAIN_MATERIAL,GLJTypeConst.INSTRUMENT];
 
     /**
      * 构造函数

+ 34 - 0
modules/main/controllers/material_replace_controller.js

@@ -0,0 +1,34 @@
+/**
+ * Created by zhang on 2018/9/12.
+ */
+
+let materialFacade = require('../facade/material_replace_facade');
+let logger = require("../../../logs/log_helper").logger;
+let controller = {
+    getMaterial:async function(req) {
+        let data = req.body.data;
+        return await materialFacade.findMaterial(JSON.parse(data),req.session.sessionCompilation._id);
+
+    },
+    replace:async function(req){
+        let data = req.body.data;
+        return await materialFacade.replace(JSON.parse(data));
+    },
+};
+
+module.exports ={
+    action:async function(req,res){//自动跳转到URL对应的controller方法
+        let result={
+            error:0
+        };
+        try {
+            let functionName = req.url.replace(/\//g,"");
+            result.data = controller[functionName]?await controller[functionName](req):"";
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        res.json(result);
+    }
+};

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

@@ -28,8 +28,7 @@ module.exports = {
     getData: function (req, res) {
         //add
         console.log(`------------------------------------------`);
-        console.log(req.session.sessionUser);
-        console.log(req.session.userAccount);
+        console.log(`${req.session.sessionUser.real_name}--id:${req.session.sessionUser.id}--取getdata数据`);
         console.log(`------------------------------------------`);
         //add
         if(typeof req.body.data === 'object'){

+ 42 - 75
modules/main/controllers/ration_controller.js

@@ -5,9 +5,39 @@ var rationData = require('../models/ration');
 var ration_glj_facade = require('../../ration_glj/facade/ration_glj_facade');
 var ration_facade = require('../facade/ration_facade');
 let logger = require("../../../logs/log_helper").logger;
+let controller = {
+    insertGLJAsRation:async function (req){
+        let data = req.body.data;
+        data = JSON.parse(data);
+        return await ration_glj_facade.insertGLJAsRation(data);
+    },
+    replaceRations:async function (req) {
+        let data = req.body.data;
+        data = JSON.parse(data);
+        let userID = req.session.sessionUser.id;
+        return await ration_facade.replaceRations(userID,data,req.session.sessionCompilation);
+    },
+    addNewRation:async function(req) {
+        let data = req.body.data;
+        if(typeof data === 'object'){
+            data = JSON.stringify(data);
+        }
+        data = JSON.parse(data);
+        return await ration_facade.addNewRation(data,req.session.sessionCompilation);
+    },
+    addMultiRation: async function (req) {
+        let data = req.body.data;
+        if(typeof data === 'object'){
+            data = JSON.stringify(data);
+        }
+        data = JSON.parse(data);
+        return await ration_facade.addMultiRation(data.newDatas,req.session.sessionCompilation);
+    }
+};
+
 
 //统一回调函数
-var callback = function(req, res, err, message, data){
+let callback = function(req, res, err, message, data){
     res.json({error: err, message: message, data: data});
 };
 
@@ -43,85 +73,22 @@ module.exports = {
             }
         });
     },
-    insertGLJAsRation:insertGLJAsRation,
-    replaceRations:replaceRations,
-    addNewRation:addNewRation,
-    addMultiRation: addMultiRation
-};
-
-async function addNewRation(req,res) {
-    let result={
-        error:0
-    }
-    try {
-        let data = req.body.data;
-        if(typeof data === 'object'){
-            data = JSON.stringify(data);
+    action:async function(req,res){//自动跳转到URL对应的controller方法
+        let result={
+            error:0
         }
-        data = JSON.parse(data);
-        result.data = await ration_facade.addNewRation(data);
-    }catch (err){
-        logger.err(err);
-        result.error=1;
-        result.message = err.message;
-    }
-    res.json(result);
-}
-
-async function addMultiRation(req,res) {
-    let result={
-        error:0
-    }
-    try {
-        let data = req.body.data;
-        if(typeof data === 'object'){
-            data = JSON.stringify(data);
+        try {
+            let functionName = req.url.replace(/\//g,"");
+            result.data = controller[functionName]?await controller[functionName](req):"";
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
         }
-        data = JSON.parse(data);
-        console.log(`data`);
-        console.log(data);
-        result.data = await ration_facade.addMultiRation(data.newDatas);
-    }catch (err){
-        logger.err(err);
-        result.error=1;
-        result.message = err.message;
+        res.json(result);
     }
-    res.json(result);
-}
-
-async function replaceRations(req,res) {
-    let result={
-        error:0
-    };
-    try {
-        let data = req.body.data;
-        data = JSON.parse(data);
-        let userID = req.session.sessionUser.id;
-        result.data = await ration_facade.replaceRations(userID,data);
-    }catch (err){
-        logger.err(err);
-        result.error=1;
-        result.message = err.message;
-    }
-    res.json(result);
 };
 
 
-async function insertGLJAsRation(req, res){
-    let result={
-        error:0
-    }
-    try {
-        let data = req.body.data;
-        data = JSON.parse(data);
-        let datas= await ration_glj_facade.insertGLJAsRation(data);
-        result.data=datas;
-    }catch (err){
-        logger.err(err);
-        result.error=1;
-        result.message = err.message;
-    }
-    res.json(result);
 
 
-}

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

@@ -221,10 +221,12 @@ function generateBillTasks(data) {
 
 
 async function insertMany(datas,model) {
+    let tem = [];
     while (datas.length>1000){//因为mongoose限制了批量插入的条数为1000.所以超出限制后需要分批插入
         let newList = datas.splice(0,1000);//一次插入1000条
         await model.insertMany(newList);
+        tem = tem.concat(newList);
     }
     await model.insertMany(datas);
-
+    if(tem.length > 0) datas.push(...tem);//还原数组
 }

+ 122 - 0
modules/main/facade/material_replace_facade.js

@@ -0,0 +1,122 @@
+/**
+ * Created by zhang on 2018/9/12.
+ */
+let logger = require("../../../logs/log_helper").logger;
+let mongoose = require('mongoose');
+let material_lib = mongoose.model('std_material_replace_lib');
+let replace_bills = mongoose.model('std_replace_bills');
+let replace_material = mongoose.model('std_replace_material');
+let _=require("lodash");
+let ration_glj_facade = require('../../ration_glj/facade/ration_glj_facade');
+let glj_calculate_facade = require('../../ration_glj/facade/glj_calculate_facade');
+
+
+module.exports = {
+    findMaterial: async function(dataMap,compilationId){
+        let libMap = {},resultMap={};
+        for(let key in dataMap) {
+            let billsLibId = dataMap[key].billsLibId;
+            let libID = libMap[compilationId + billsLibId] ? libMap[compilationId + billsLibId] : await getLibID(billsLibId, compilationId);
+            libMap[compilationId + billsLibId] = libID;
+            if (libID == null) continue;
+            let bills = await getBills(key, libID);
+            if (bills == null) continue;
+            let materialList = await getMaterialByBillsID(bills.ID);
+            resultMap[key] = {bills:bills,materialMap:_.indexBy(materialList,'code')};
+        }
+        return resultMap;
+    },
+    replace:async function(datas){
+        let resultList = [];
+        let rationMap = _.groupBy(datas,function(item){//先按定额进行分组
+            return item.glj.rationID;
+        });
+        for(let rationID in rationMap){
+           let result = await eachRationGroup(rationID,rationMap[rationID]);
+           resultList.push(result);
+        }
+        return resultList
+    }
+};
+
+async function eachRationGroup(rationID,datas) {
+    let query={rationID:rationID},gljs=[];
+    for(let d of datas){
+         query["projectID"] = d.glj.projectID;
+         gljs.push(await updateRationGLJ(d));
+    }
+    if(query.projectID){
+        let stateResult = await glj_calculate_facade.calculateQuantity(query,null,true);
+        return {rationID:rationID,name:stateResult.rationName,adjustState:stateResult.adjustState,ration_gljs:gljs}
+    }else {
+        throw new Error("人材机的项目ID有问题");
+    }
+
+}
+
+async function updateRationGLJ(data) {
+    let glj = data.glj;
+    let priceInfo = {
+        base_price: glj.basePrice,
+        market_price: glj.marketPrice
+    };
+    let [projcetGLJ_n,doc] = await ration_glj_facade.updateRationGLJFromDoc(glj,data.doc,priceInfo);
+    return {ID:glj.ID,doc:doc}
+
+}
+
+/*async function doRationGLJUpdate(data) {
+    let resutl = {};
+    let doc = data.doc;
+    let priceInfo = data.priceInfo;
+    let rg = await ration_glj.findOne(data.query);
+    let gljListModel = new GLJListModel();
+    let projectGLJ = getGLJSearchInfo(rg);
+    for (let key in doc) {
+        projectGLJ[key] = doc[key]
+    }
+    projectGLJ.base_price = priceInfo.base_price;
+    projectGLJ.market_price = priceInfo.market_price;
+    let projcetGLJ_n = await gljListModel.modifyGLJ(projectGLJ, rg);
+    doc.code = projcetGLJ_n.code;
+    doc.projectGLJID = projcetGLJ_n.id;
+    if (projcetGLJ_n.unit_price.is_add == 1) {
+        doc.createType = 'replace';
+        doc.rcode = projcetGLJ_n.original_code;
+    } else {
+        doc.createType = 'normal';
+        doc.rcode = '';
+    }
+    await ration_glj.findOneAndUpdate(data.query, doc);
+    //取价格
+    gljListModel.getGLJPrice(projcetGLJ_n);
+    doc.basePrice = projcetGLJ_n.unit_price.base_price;
+    doc.marketPrice = projcetGLJ_n.unit_price.market_price;
+    doc.adjustPrice = projcetGLJ_n.adjust_price;
+    doc.isAdd = projcetGLJ_n.unit_price.is_add;
+    resutl.doc = doc;
+    let stateResult = await glj_calculate_facade.calculateQuantity({
+        projectID: data.query.projectID,
+        rationID: data.query.rationID
+    },null,true);
+    resutl.adjustState = stateResult.adjustState;
+    resutl.name = stateResult.rationName;
+    return resutl;
+}*/
+
+
+async function getLibID(billsLibId,compilationId) {
+    let lib = await material_lib.findOne({"compilationId":compilationId,billsLibId:billsLibId});
+    if(lib) return lib.ID;
+    return null;
+}
+
+async function getBills(code,libID) {
+    let bills = await replace_bills.findOne({code:code,libID:libID});
+    if(bills) return bills;
+    return null;
+}
+
+async  function getMaterialByBillsID(billsItemID) {
+    return await replace_material.find({billsItemID:billsItemID},['code','name','specs','type','unit']);
+}

+ 50 - 27
modules/main/facade/ration_facade.js

@@ -20,13 +20,14 @@ let coeMolde = mongoose.model('std_ration_lib_coe_list');
 let _= require('lodash');
 const projectDao = require('../../pm/models/project_model').project;
 let projectModel = mongoose.model('projects');
+const fs = require('fs');
 
 module.exports = {
     replaceRations: replaceRations,
     addNewRation:addNewRation,
     addMultiRation: addMultiRation
 };
-async function addNewRation(data) {
+async function addNewRation(data,compilation) {
     let query = data.itemQuery;
     let stdRation = null;
     let startTime = +new Date();
@@ -44,16 +45,16 @@ async function addNewRation(data) {
     let addRationGLJTime = +new Date();
     console.log("插入新定额时间-------------------------------"+(addRationGLJTime - stdRationTime));
     if(stdRation){
-        return await addRationSubList(stdRation,newRation,data.needInstall);
+        return await addRationSubList(stdRation,newRation,data.needInstall,compilation);
     }else {
         return {ration:newRation};
     }
 }
 
-async function addMultiRation(datas) {
+async function addMultiRation(datas,compilation) {
     let rst = [];
     for(let data of datas){
-        let r = await addNewRation(data);
+        let r = await addNewRation(data,compilation);
         rst.push(r);
     }
     return rst;
@@ -120,12 +121,12 @@ async function insertNewRation(newData,defaultLibID,std,calQuantity) {//插入
     return newData;*/
 }
 
-async function replaceRations(userID,data) {
+async function replaceRations(userID,data,compilation) {
     let searchDao = new SearchDao();
     let recodes = [];
     for(let recode of data.nodeInfo){
         let stdRation = await searchDao.getRationItem(userID,data.libIDs,recode.newCode, null);
-        let newRecode = await replaceRation(recode,stdRation,data.defaultLibID,data.projectID,data.calQuantity);
+        let newRecode = await replaceRation(recode,stdRation,data.defaultLibID,data.projectID,data.calQuantity,compilation);
         if(newRecode){
             recodes.push(newRecode);
         }else {
@@ -135,25 +136,25 @@ async function replaceRations(userID,data) {
     return recodes;
 }
 
-async function replaceRation(nodeInfo,stdRation,defaultLibID,projectID,calQuantity) {
+async function replaceRation(nodeInfo,stdRation,defaultLibID,projectID,calQuantity,compilation) {
     if(nodeInfo.newCode == null||nodeInfo.newCode ==""){//说明是删除编号,则要变成一条空定额
         await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等
         return await setEmptyRation(projectID,nodeInfo.ID);
     }else if(stdRation){
         await deleRationSubRecode(projectID,nodeInfo.ID);//删除定额下挂的各种数据,如定额工料机等
         let newRation = await updateRation(stdRation,defaultLibID,nodeInfo.ID,nodeInfo.billsItemID,projectID,calQuantity);//生成并插入新的定额
-        return await addRationSubList(stdRation,newRation,nodeInfo.needInstall);
+        return await addRationSubList(stdRation,newRation,nodeInfo.needInstall,compilation);
     }else {
         return null;
     }
 }
 
-async function addRationSubList(stdRation,newRation,needInstall) {
+async function addRationSubList(stdRation,newRation,needInstall,compilation) {
     let startTime = +new Date();
     let ration_gljs = await addRationGLJ(stdRation,newRation);
     let addRationGLJTime = +new Date();
     console.log("添加定额工料机时间-----"+(addRationGLJTime - startTime));
-    let ration_coes = await addRationCoe(stdRation,newRation);
+    let ration_coes = await addRationCoe(stdRation,newRation,compilation);
     let addRationCoeTime = +new Date();
     console.log("添加定额coe时间-----"+(addRationCoeTime - addRationGLJTime));
     let ration_installs = [];
@@ -203,7 +204,7 @@ async function addRationInstallFee(std,newRation) {
     return install_fee_list;
 }
 
-async function addRationCoe(std,newRation) {
+async function addRationCoe(std,newRation,compilation) {
     let ration_coe_list = [];
     let seq = 0;
     if(std.hasOwnProperty('rationCoeList')&&std.rationCoeList.length>0){//添加标准库的工料机
@@ -225,33 +226,55 @@ async function addRationCoe(std,newRation) {
             }
         }
     }
+    let lastCoe = await getCustomerCoe(newRation.projectID,newRation.ID,seq,compilation);
+    ration_coe_list.push(lastCoe);
+    await ration_coe.insertMany(ration_coe_list);
+    return ration_coe_list;
+
+}
+
+function getCustomerCoeData() {
+    var coeList = [
+         {amount:1, operator:'*', gljCode:null, coeType:'定额'},
+        { amount:1, operator:'*', gljCode:null, coeType:'人工'},
+        { amount:1, operator:'*', gljCode:null, coeType:'材料'},
+        { amount:1, operator:'*', gljCode:null, coeType:'机械'},
+        { amount:1, operator:'*', gljCode:null, coeType:'主材'},
+        { amount:1, operator:'*', gljCode:null, coeType:'设备'}
+    ];
+    return coeList;
+};
+
+
+async function getCustomerCoe(projectID,rationID,seq,compilation){//取自定义乘系数,根据编办不同,内容可能不同
+    //生成默认的自定义乘系数
     let lastCoe ={
         coeID:-1,
         name : '自定义系数',
         content:'人工×1,材料×1,机械×1,主材×1,设备×1',
         isAdjust:0,
         seq:seq,
-        rationID : newRation.ID,
-        projectID : newRation.projectID
+        rationID : rationID,
+        projectID : projectID
     };
     lastCoe.ID = uuidV1();
     lastCoe.coes = getCustomerCoeData();
-    ration_coe_list.push(lastCoe);
-    await ration_coe.insertMany(ration_coe_list);
-    return ration_coe_list;
-
+    try {
+    //查看编办中有没有重写路径
+     if(compilation.overWriteUrl && compilation.overWriteUrl!=""){
+         let overWrite = require("../../.."+compilation.overWriteUrl);
+         if(overWrite.getCusCoeContent) lastCoe.content = overWrite.getCusCoeContent();
+         if(overWrite.getCustomerCoeData) lastCoe.coes = overWrite.getCustomerCoeData();
+     }
+     return lastCoe
+   }catch (err){
+       console.log("读取自定义系数重写文件失败");
+       console.log(err.message);
+       return lastCoe
+   }
 }
 
-function getCustomerCoeData() {
-    var coeList = [];
-    coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'定额'});
-    coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'人工'});
-    coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'材料'});
-    coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'机械'});
-    coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'主材'});
-    coeList.push({ amount:1, operator:'*', gljCode:null, coeType:'设备'});
-    return coeList;
-};
+
 
 async function addRationGLJ(std,newRation) {
     let newRationGLJList = [];

+ 16 - 0
modules/main/routes/material_replace_route.js

@@ -0,0 +1,16 @@
+/**
+ * Created by zhang on 2018/9/12.
+ */
+
+let express = require('express');
+let materialController = require('../controllers/material_replace_controller');
+
+module.exports = function (app) {
+
+    var materialRouter = express.Router();
+
+    materialRouter.post('/getMaterial', materialController.action);
+    materialRouter.post('/replace', materialController.action);//材料替换,其实是材料修改
+
+    app.use('/material',materialRouter);
+}

+ 4 - 4
modules/main/routes/ration_route.js

@@ -9,10 +9,10 @@ module.exports = function (app) {
     rationRouter.post('/getData', rationController.getData);
     rationRouter.post('/getItemTemplate', rationController.getItemTemplate);
     rationRouter.post('/allocIDs', rationController.allocIDs);
-    rationRouter.post('/insertGLJAsRation', rationController.insertGLJAsRation);
-    rationRouter.post('/replaceRations', rationController.replaceRations);
-    rationRouter.post('/addNewRation', rationController.addNewRation);
-    rationRouter.post('/addMultiRation', rationController.addMultiRation);
+    rationRouter.post('/insertGLJAsRation', rationController.action);
+    rationRouter.post('/replaceRations', rationController.action);
+    rationRouter.post('/addNewRation', rationController.action);
+    rationRouter.post('/addMultiRation', rationController.action);
 
     app.use('/ration', rationRouter);
 };

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

@@ -159,6 +159,21 @@ module.exports = {
             callback(req, res, err, message, data);
         });
     },
+    defaultSettings: async function(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let projectID = data.projectID;
+            let defaultSettingSc = await ProjectsData.defaultSettings(req.session.sessionUser.id, req.session.sessionCompilation._id, projectID);
+            if(!defaultSettingSc){
+                throw '恢复失败';
+            }
+            res.json({error: 0, message: '恢复成功', data: null});
+        }
+        catch(error){
+            console.log(error);
+            res.json({error: 1, message: error, data: null});
+        }
+    },
  /*   copyProjects: function (req, res) {
         let data = JSON.parse(req.body.data);
         ProjectsData.copyUserProjects(req.session.sessionUser.id, req.session.sessionCompilation._id, data.updateData, function (err, message, data) {
@@ -254,7 +269,7 @@ module.exports = {
             billValuation: JSON.stringify(billValuation),
             rationValuation: JSON.stringify(rationValuation),
             engineeringList: JSON.stringify(engineering.List),
-            versionName: sessionCompilation.name + '免费版',
+            versionName: sessionCompilation.name + request.session.compilationVersion,
             LicenseKey:config.getLicenseKey(process.env.NODE_ENV)
         };
 

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

@@ -14,6 +14,7 @@ import {
     calcOptions,
     tenderSetting
 } from './project_property_template';
+import optionSetting from '../../options/models/optionTypes';
 import fixedFlag from '../../common/const/bills_fixed';
 let FeeRateFiles = mongoose.model('fee_rate_file');
 let counter = require("../../../public/counter/counter.js");
@@ -30,6 +31,9 @@ let BillsModel = require("../../main/models/bills").model;
 let _ = require('lodash');
 
 let Projects = mongoose.model('projects');
+let mainColLibModel = mongoose.model('std_main_col_lib');
+let projSettingModel = mongoose.model('proj_setting');
+let optionModel = mongoose.model('options');
 let projectType = {
     folder: 'Folder',
     tender: 'Tender',
@@ -778,6 +782,34 @@ ProjectsDAO.prototype.getBasicInfo = async function (projectID) {
     return constructionProject.property.basicInformation;
 };
 
+//恢复默认系统设置
+ProjectsDAO.prototype.defaultSettings = async function (userID, compilationId, projectID) {
+    let project = await Projects.findOne({ID: projectID});
+    if(!project){
+        return false;
+    }
+    let cloneProperty = _.cloneDeep(project.property);
+    //关于计算
+    cloneProperty.billsCalcMode = 0;
+    cloneProperty.zanguCalcMode = 0;
+    cloneProperty.calcOptions = calcOptions;
+    //清单工程量精度
+    cloneProperty.billsQuantityDecimal = billsQuantityDecimal;
+    //小数位数
+    cloneProperty.decimal = defaultDecimal;
+    //呈现选项
+    cloneProperty.displaySetting = displaySetting;
+    //列设置
+    let stdColLib = await mainColLibModel.findOne({ID: project.property.colLibID});
+    if(stdColLib){
+        await projSettingModel.update({projectID: projectID}, {$set: {main_tree_col: stdColLib.main_tree_col}});
+    }
+    //系统选项
+    await optionModel.update({user_id: userID, compilation_id: compilationId}, {$set: {options: optionSetting}});
+    await Projects.update({ID: projectID}, {$set: {property: cloneProperty}});
+    return true;
+};
+
 
 
 module.exports ={    project: new ProjectsDAO(),

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

@@ -48,6 +48,7 @@ module.exports = function (app) {
     pmRouter.post('/getUnitFile', pmController.getUnitFileList);
     pmRouter.post('/getFeeRateFile', pmController.getFeeRateFileList);
     pmRouter.post('/updateFiles', pmController.updateFiles);
+    pmRouter.post('/defaultSettings', pmController.defaultSettings);
     //GC
     pmRouter.post('/getGCDatas', pmController.getGCDatas);
     pmRouter.post('/recGC', pmController.recGC);

+ 18 - 4
modules/ration_glj/facade/glj_calculate_facade.js

@@ -28,6 +28,15 @@ let stateSeq ={
     cusCoe:6,
     adjMak:7
 };
+//自定义乘系数与定额工料机类型映射表
+let coeTypeMap = {
+    "人工":1,
+    "材料":2,
+    "机械":3,
+    "施工机具":3,
+    "主材":4,
+    "设备":5
+};
 
 
 async function calculateQuantity(query,noNeedCal,refreshRationName = false){
@@ -36,7 +45,7 @@ async function calculateQuantity(query,noNeedCal,refreshRationName = false){
              glj_result:[],
              rationID:query.rationID
          };
-         let impactRation = await ration.findOne({projectID:query.projectID,ID:query.rationID,deleteInfo:null});
+         let impactRation = await ration.findOne({ID:query.rationID,projectID:query.projectID});
          let gljList = await ration_glj.find(query);//{projectID:query.projectID,rationID:query.rationID}
          let coeList = await ration_coe.find({projectID:query.projectID,rationID:query.rationID}).sort('seq').exec();
          let assList=[];
@@ -299,7 +308,7 @@ function everyCoe(quantity,coe,glj) {
                 coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
             } else if(coe.coes[i].coeType=='定额'){
                 coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
-            }else if(coe.coes[i].coeType==getGLJTypeByID(glj.type)){
+            }else if(coeTypeMap[coe.coes[i].coeType]==getRootGLJType(glj.type).ID){
                 coeQuantity = getCalculateResult(coeQuantity,coe.coes[i]);
             }
         }
@@ -314,7 +323,7 @@ function calculateQuantityByCustomerCoes(quantify,coe,glj) {
         return getCalculateResult(quantify, coe.coes[0])
     }else {
         for(let i=1;i<coe.coes.length;i++){
-            if(coe.coes[i].coeType.search(getGLJTypeByID(glj.type))!=-1){
+            if(coeTypeMap[coe.coes[i].coeType]==getRootGLJType(glj.type).ID){
                 return getCalculateResult(quantify,coe.coes[i])
             }
         }
@@ -344,10 +353,15 @@ function getCalculateResult(quantify,c) {
     return q;
 }
 
-function getGLJTypeByID(id) {
+function getRootGLJType(id){
     let glj_type_object = glj_type_util.getStdGljTypeCacheObj();
     let topTypeId = glj_type_object.getTopParentIdByItemId(id);
     let type = glj_type_object.getItemById(topTypeId);
+    return type;
+}
+
+function getGLJTypeByID(id) {
+    let type = getRootGLJType(id);
     if(type!=undefined){
         return type.fullName;
     }else {

+ 14 - 7
modules/ration_glj/facade/ration_glj_facade.js

@@ -44,7 +44,8 @@ module.exports = {
     getRationTypeGLJQuantity:getRationTypeGLJQuantity,
     getInfoFromProjectGLJ:getInfoFromProjectGLJ,
     createNewRecord:createNewRecord,
-    getGLJSearchInfo:getGLJSearchInfo
+    getGLJSearchInfo:getGLJSearchInfo,
+    updateRationGLJFromDoc:updateRationGLJFromDoc
 }
 
 let operationMap = {
@@ -694,11 +695,7 @@ async function updateRationGLJByEdit(data) {
     return result;
 }
 
-async function doRationGLJUpdate(data) {
-    let resutl = {};
-    let doc = data.doc;
-    let priceInfo = data.priceInfo;
-    let rg = await ration_glj.findOne(data.query);
+async function updateRationGLJFromDoc(rg,doc,priceInfo) {
     let gljListModel = new GLJListModel();
     let projectGLJ = getGLJSearchInfo(rg);
     for (let key in doc) {
@@ -716,8 +713,18 @@ async function doRationGLJUpdate(data) {
         doc.createType = 'normal';
         doc.rcode = '';
     }
-    await ration_glj.findOneAndUpdate(data.query, doc);
+    await ration_glj.findOneAndUpdate({ID:rg.ID}, doc);
+    return [projcetGLJ_n,doc]
+}
+
+
+async function doRationGLJUpdate(data) {
+    let resutl = {};
+    let priceInfo = data.priceInfo;
+    let rg = await ration_glj.findOne(data.query);
+    let [projcetGLJ_n,doc] = await updateRationGLJFromDoc(rg,data.doc,priceInfo);
     //取价格
+    let gljListModel = new GLJListModel();
     gljListModel.getGLJPrice(projcetGLJ_n);
     doc.basePrice = projcetGLJ_n.unit_price.base_price;
     doc.marketPrice = projcetGLJ_n.unit_price.market_price;

+ 3 - 3
modules/std_billsGuidance_lib/facade/facades.js

@@ -31,15 +31,15 @@ async function getBillsGuideLibs(findData) {
 
 
 async function getLibWithBills(libID){
-    let guidanceLib = await getBillsGuideLibs({ID: libID, deleted: false});
+    let guidanceLib = await getBillsGuideLibs({ID: libID});
     if(guidanceLib.length === 0){
         throw '不存在此指引库!';
     }
-    let billsLib = await stdBillsLibModel.findOne({billsLibId: guidanceLib[0].billsLibId, deleted: false});
+    let billsLib = await stdBillsLibModel.findOne({billsLibId: guidanceLib[0].billsLibId});
     if(!billsLib){
         throw '引用的清单规则库不存在!';
     }
-    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId, deleted: false});
+    let bills = await stdBillsModel.find({billsLibId: billsLib.billsLibId}, '-_id -ruleText -recharge');
     return {guidanceLib: guidanceLib[0], bills};
 }
 

+ 5 - 1
modules/users/controllers/boot_controller.js

@@ -24,11 +24,15 @@ class BootController extends BaseController {
         let sessionUser = request.session.sessionUser;
         let compilationId = request.params.compilation;
         let sessionCompilation = request.session.sessionCompilation;
+        let compilationVersion = request.session.compilationVersion;
 
         // 判断是否有存入编办信息
         if (sessionCompilation === undefined && compilationId !== '') {
             let compilationModel = new CompilationModel();
             let compilationData = await compilationModel.getCompilationById(compilationId);
+            // 判断当前用户的是使用免费版还是专业版
+            compilationVersion = await userModel.getVersionFromUpgrade(sessionUser.ssoId, compilationId);
+            request.session.compilationVersion = compilationVersion;
             request.session.sessionCompilation = compilationData;
             if(sessionUser.latest_used !== compilationId) userModel.updateLatestUsed(sessionUser.id,compilationId);
         }
@@ -44,7 +48,7 @@ class BootController extends BaseController {
             companyTypeList: userModel.companyType,
             companyScaleList: userModel.companyScale,
             compilation: request.params.compilation,
-            versionName: request.session.sessionCompilation.name + '免费版'
+            versionName: request.session.sessionCompilation.name + request.session.compilationVersion
         };
         response.render('users/html/login-infoinput', renderData);
     }

+ 4 - 0
modules/users/controllers/login_controller.js

@@ -89,6 +89,9 @@ class LoginController {
             if (preferenceSetting.login_ask === 0 && !sessionCompilation &&
                 preferenceSetting.select_version !== '') {
                 let compilationData = await compilationModel.getCompilationById(preferenceSetting.select_version);
+                // 判断当前用户的是使用免费版还是专业版
+                let compilationVersion = await userModel.getVersionFromUpgrade(sessionUser.ssoId, preferenceSetting.select_version);
+                request.session.compilationVersion = compilationVersion;
                 request.session.sessionCompilation = compilationData;
                 if(request.session.sessionUser.latest_used !== preferenceSetting.select_version) await userModel.updateLatestUsed(request.session.sessionUser.id,preferenceSetting.select_version);
             }
@@ -97,6 +100,7 @@ class LoginController {
             console.log(error);
             return response.json({error: 1, msg: error});
         }
+        console.log(`${request.session.sessionUser.real_name}--id:${request.session.sessionUser.id}--登录了系统`);
         response.json({
             error: 0,
             msg: '',

+ 49 - 4
modules/users/controllers/user_controller.js

@@ -38,7 +38,7 @@ class UserController extends BaseController {
             provinceList: userModel.province,
             companyTypeList: userModel.companyType,
             companyScaleList: userModel.companyScale,
-            versionName: request.session.sessionCompilation.name + '免费版'
+            versionName: request.session.sessionCompilation.name + request.session.compilationVersion
         };
         response.render('users/html/user-info', renderData);
     }
@@ -119,12 +119,54 @@ class UserController extends BaseController {
             userData: userData,
             logList: logList,
             pages: pageData,
-            versionName: request.session.sessionCompilation.name + '免费版'
+            versionName: request.session.sessionCompilation.name + request.session.compilationVersion
         };
         response.render('users/html/user-safe', renderData);
     }
 
     /**
+     * 产品激活页面
+     *
+     * @param request
+     * @param response
+     * @return {void}
+     */
+    async buy(request, response) {
+        let userData = [];
+        let compilationList = [];
+        try {
+            // 获取编办信息
+            let compilationModel = new CompilationModel();
+            compilationList = await compilationModel.getList();
+
+            // 获取当前用户信息
+            let sessionUser = request.session.sessionUser;
+            let userModel = new UserModel();
+            userData = await userModel.findDataBySsoId(sessionUser.ssoId);
+            if (userData.upgrade_list !== undefined) {
+                let userUpgradeList = userData.upgrade_list;
+                for (let index in userUpgradeList) {
+                    let oneCompilationIndex = compilationList.findIndex(function (item) {
+                        return item.id === userUpgradeList[index].compilationID;
+                    });
+                    if (oneCompilationIndex !== -1) {
+                        compilationList[oneCompilationIndex].isUpgrade = userUpgradeList[index].isUpgrade;
+                    }
+                }
+            }
+        } catch(error) {
+            console.log(error);
+        }
+
+        let renderData = {
+            userData: userData,
+            compilationList: compilationList,
+            versionName: request.session.sessionCompilation.name + request.session.compilationVersion
+        };
+        response.render('users/html/user-buy', renderData);
+    }
+
+    /**
      * 偏好设置页面
      *
      * @param {object} request
@@ -151,7 +193,7 @@ class UserController extends BaseController {
         let renderData = {
             preferenceSetting: preferenceSetting,
             compilationList: compilationList,
-            versionName: request.session.sessionCompilation.name + '免费版'
+            versionName: request.session.sessionCompilation.name + request.session.compilationVersion
         };
         response.render('users/html/user-set', renderData);
     }
@@ -185,7 +227,10 @@ class UserController extends BaseController {
                 // 查找对应编办
                 let compilationModel = new CompilationModel();
                 let compilationData = await compilationModel.getCompilationById(selectVersion);
-
+                // 判断当前用户的是使用免费版还是专业版
+                let userModel = new UserModel();
+                let compilationVersion = await userModel.getVersionFromUpgrade(sessionUserData.ssoId, compilationData._id);
+                request.session.compilationVersion = compilationVersion;
                 request.session.sessionCompilation = compilationData;
             }
         } catch (error) {

+ 21 - 0
modules/users/models/user_model.js

@@ -228,6 +228,27 @@ class UserModel extends BaseModel {
         return await this.db.findOneAndUpdate({_id: userObjId}, {$pull: {versionInfo: {compilationId: compilationId}}});
     }
 
+    /**
+     * 判断用户使用免费版还是专业版
+     *
+     * @param ssoId
+     * @param compilationId
+     * @return {version}
+     */
+    async getVersionFromUpgrade(ssoId, compilationId){
+        let version = '免费版';
+        let userData = await this.findDataBySsoId(ssoId);
+        if (userData.upgrade_list !== undefined) {
+            let compilationInfo = userData.upgrade_list.find(function (item) {
+                return item.compilationID === compilationId;
+            });
+            if (compilationInfo !== undefined && compilationInfo.isUpgrade === true) {
+                version = '专业版';
+            }
+        }
+        return version;
+    }
+
 }
 
 export default UserModel;

+ 1 - 0
modules/users/routes/user_route.js

@@ -16,6 +16,7 @@ module.exports = function (app) {
 // action定义区域
     router.get('/info', userController.init, userController.info);
     router.get('/safe', userController.init, userController.safe);
+    router.get('/buy', userController.init, userController.buy);
     router.get('/preferences', userController.init, userController.preferences);
     router.post('/save-preferences', userController.init, userController.savePreferences);
     router.post('/info', userController.init, userController.saveData);

+ 13 - 0
public/web/sheet/sheet_common.js

@@ -335,6 +335,19 @@ var sheetCommonObj = {
         };
         return new CustomerCoeCellType();
     },
+    scrollSheetForOption:function (sheet,cxt,cellRect,row,options){
+        let topRow = sheet.getViewportTopRow(1);
+        if(row == topRow) return;//已经是最顶行了
+        let length = options&&options.length>0?options.length:1;
+        let height = cxt.canvas.height;
+        let startY = cellRect.y+cellRect.height;//下拉框的起始显示位置
+        let endY =  startY + length * cellRect.height;//下拉框的结束显示位置
+        if(endY <= height) return;  //如果没有超出显示位置,直接返回
+        let overRow =  Math.ceil((endY - height)/cellRect.height);//超出的行数
+        let showRow = topRow + overRow > row?row:topRow + overRow;
+        sheet.showRow(showRow, GC.Spread.Sheets.VerticalPosition.top);
+
+    },
     setSelectButton(row,col,sheet,header){
         let getSelectButton = function (cellWidth=100) {
             function moreButton() {

+ 10 - 2
public/web/sheet/sheet_data_helper.js

@@ -168,6 +168,7 @@ var SheetDataHelper = {
                     }
                     this._fixedTipElement = div;
                 }
+                $(this._fixedTipElement).width('');
                 $(this._fixedTipElement).html(text);
                 if (!this._toolTipElement) {
                     let div = $('#autoTip')[0];
@@ -184,16 +185,23 @@ var SheetDataHelper = {
                         document.body.insertBefore(div, null);
                     }
                     this._toolTipElement = div;
+                    $(this._toolTipElement).width('');
                     //实时读取位置信息
                     if(hitinfo.sheet && hitinfo.sheet.getParent().qo){
                         setting.pos = SheetDataHelper.getObjPos(hitinfo.sheet.getParent().qo);
                     }
                     $(this._toolTipElement).html(text);
                     //定额库定额特殊处理
-                    if($(hitinfo.sheet.getParent().qo).attr('id') === 'stdSectionRations'){
+                    if($(hitinfo.sheet.getParent().qo).attr('id') === 'stdSectionRations' ||
+                        $(hitinfo.sheet.getParent().qo).hasClass('main-data-side-search')){
                         let divWidth = $(this._fixedTipElement).width(),
                             divHeight = $(this._fixedTipElement).height();
-                        $(this._toolTipElement).css("top", setting.pos.y  + hitinfo.y - divHeight).css("left", setting.pos.x - divWidth);
+                        if(divWidth > 600){
+                            divWidth = 590;
+                           $(this._toolTipElement).width(divWidth);
+                        }
+                        let top = setting.pos.y  + hitinfo.y - divHeight < 0 ? 0 : setting.pos.y  + hitinfo.y - divHeight;
+                        $(this._toolTipElement).css("top", top).css("left", setting.pos.x - divWidth);
                     }
                     else{
                         $(this._toolTipElement).css("top", setting.pos.y + hitinfo.y +15).css("left", setting.pos.x + hitinfo.x + 15);

+ 37 - 20
public/web/tree_sheet/tree_sheet_helper.js

@@ -125,7 +125,7 @@ var TREE_SHEET_HELPER = {
                 }
             }
             setting.cols.forEach(function (colSetting, iCol) {
-                var cell = sheet.getCell(iRow, iCol, GC.Spread.Sheets.SheetArea.viewport);
+
    /* if(typeof projectObj !== 'undefined'){ 7/28  取消黑体显示
                     let boldFontStyle = projectObj.getBoldFontStyle(node, colSetting);
                     sheet.setStyle(iRow, iCol, boldFontStyle);
@@ -179,6 +179,8 @@ var TREE_SHEET_HELPER = {
 
                 }
 
+                if(colSetting.visible == false) return;//隐藏列不做其它操作
+                var cell = sheet.getCell(iRow, iCol, GC.Spread.Sheets.SheetArea.viewport);
                 if (colSetting.data.getText && Object.prototype.toString.apply(colSetting.data.getText) === "[object Function]") {
                     cell.value(colSetting.data.getText(node));
                 } else {
@@ -377,21 +379,18 @@ var TREE_SHEET_HELPER = {
                 hitinfo.sheet.repaint();
             }
         };
-        TreeNodeCellType.prototype.processMouseEnter = function(hitinfo){
-            let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
-            let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
-            if(tag&&tag!=''){
-                TREE_SHEET_HELPER.showTipsDiv(tag,setting,hitinfo);
+        TreeNodeCellType.prototype.processMouseMove = function(hitinfo){//造价书主界面,当鼠标移动到单元格最右往左50个像素内时才显示悬浮提示内容
+            if (hitinfo.sheet.name()!=="mainSheet") return;//只有在造价书主界面才显示
+            let offset = 20;//从右向左显示的像素范围
+            let leftX = hitinfo.cellRect.x + hitinfo.cellRect.width;//最右边的坐标
+            if(leftX - hitinfo.x <= offset){//如果鼠标移动到的位置是在显示的范围内显示悬浮提示
+                TREE_SHEET_HELPER.delayShowTips(hitinfo,setting);
+            }else {//如果移出了范围,隐藏悬浮提示
+                TREE_SHEET_HELPER.hideTipsDiv();
             }
         };
         TreeNodeCellType.prototype.processMouseLeave = function (hitinfo) {
-            let me = TREE_SHEET_HELPER;
-            TREE_SHEET_HELPER.tipDiv = 'hide';
-            if (me._toolTipElement) {
-                $(me._toolTipElement).hide();
-                me._toolTipElement = null;
-            };
-            TREE_SHEET_HELPER.tipDivCheck();//延时检查:当tips正在show的时候,就调用了hide方法,会导致tips一直存在,所以设置一个超时处理
+            TREE_SHEET_HELPER.hideTipsDiv();
         };
 
         let TipCellType = function () {};
@@ -444,13 +443,7 @@ var TREE_SHEET_HELPER = {
             TREE_SHEET_HELPER.showTipsDiv(text,setting,hitinfo);
         };
         TipCellType.prototype.processMouseLeave = function (hitinfo) {
-            let me = TREE_SHEET_HELPER;
-            TREE_SHEET_HELPER.tipDiv = 'hide';
-            if (me._toolTipElement) {
-                $(me._toolTipElement).hide();
-                me._toolTipElement = null;
-            };
-            TREE_SHEET_HELPER.tipDivCheck();//延时检查:当tips正在show的时候,就调用了hide方法,会导致tips一直存在,所以设置一个超时处理
+            TREE_SHEET_HELPER.hideTipsDiv();
         }
 
         TREE_SHEET_HELPER.protectdSheet(sheet);
@@ -513,6 +506,16 @@ var TREE_SHEET_HELPER = {
             }
         }
     },
+    hideTipsDiv:function () {
+        TREE_SHEET_HELPER.tipTimeStamp = +new Date();//这个是为了造价书清单编号树节点的那个延时显示而打的时间戳,防止已经要隐藏的提示框,延时显示
+        let me = TREE_SHEET_HELPER;
+        TREE_SHEET_HELPER.tipDiv = 'hide';
+        if (me._toolTipElement) {
+            $(me._toolTipElement).hide();
+            me._toolTipElement = null;
+        }
+        TREE_SHEET_HELPER.tipDivCheck();//延时检查:当tips正在show的时候,就调用了hide方法,会导致tips一直存在,所以设置一个超时处理
+    },
     tipDivCheck(){
         setTimeout(function () {
             let tips = $('#autoTip');
@@ -523,5 +526,19 @@ var TREE_SHEET_HELPER = {
                 TREE_SHEET_HELPER._toolTipElement = null;
             }
         },600)
+    },
+    delayShowTips:function(hitinfo,setting){//延时显示
+        let delayTimes = 500; //延时时间
+        let now_timeStamp = +new Date();
+        TREE_SHEET_HELPER.tipTimeStamp = now_timeStamp;
+        setTimeout(function () {
+            if(now_timeStamp - TREE_SHEET_HELPER.tipTimeStamp == 0){//鼠标停下的时候才显示
+                let text = hitinfo.sheet.getText(hitinfo.row, hitinfo.col);
+                let tag = hitinfo.sheet.getTag(hitinfo.row, hitinfo.col);
+                if(tag&&tag!=''){
+                    TREE_SHEET_HELPER.showTipsDiv(tag,setting,hitinfo);
+                }
+            }
+        },delayTimes);
     }
 };

+ 1 - 1
web/building_saas/complementary_glj_lib/html/tools-gongliaoji.html

@@ -107,8 +107,8 @@
                     <h5 class="text-danger" id="alertGljTxt">编号和类型不可为空!是否取消操作?</h5>
                 </div>
                 <div class="modal-footer">
-                    <button type="button" class="btn btn-secondary" id="aleCanceBtn" data-dismiss="modal">取消</button>
                     <a href="javascript: void(0);" id="aleConfBtn" class="btn btn-danger" data-dismiss="modal">确认</a>
+                    <button type="button" class="btn btn-secondary" id="aleCanceBtn" data-dismiss="modal">取消</button>
                 </div>
             </div>
         </div>

+ 151 - 96
web/building_saas/complementary_glj_lib/js/glj.js

@@ -212,6 +212,7 @@ let repositoryGljObj = {
         me.workBook = sheetOpr.buildSheet(container, me.setting, 30);
         sheetCommonObj.spreadDefaultStyle(me.workBook);
         me.repositoryGljDelOpr();
+        me.onContextmenuOpr();
         me.bindEnterKey();
         me.setUnitCombo(me.workBook.getActiveSheet(), me.setting.header);
         me.workBook.getActiveSheet().bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
@@ -333,26 +334,30 @@ let repositoryGljObj = {
         //混凝土202、砂浆203、配合比204、机械3
         if(typeof info.oldSelections || info.oldSelections.length === 0 && info.newSelections.length > 0 || info.oldSelections[0].row !== info.newSelections[0].row){
             let row = info.newSelections[0].row;
-            sheetOpr.cleanSheet(that.workBook.getSheet(0), that.setting, -1);
-            me.workBook.focus(true);
-            me.currentComponent = [];
-            that.workBook.getSheet(0).setRowCount(5);
-            if(row < me.currentCache.length){
-                //标记当前工料机
-                me.currentGlj = me.currentCache[row];
-                if(allowComponent.includes(me.currentCache[row].gljType)){
-                    //展示数据
-                    if(me.currentGlj.component.length > 0){
-                        me.currentComponent = me.getCurrentComponent(me.currentGlj.component);
-                        if(me.currentComponent.length > 0){
-                            sheetOpr.showData(that.workBook.getSheet(0), that.setting, me.currentComponent);
-                        }
+            me.initSel(row);
+        }
+    },
+    initSel: function (row) {
+        let me = repositoryGljObj, that = gljComponentOprObj;
+        sheetOpr.cleanData(that.workBook.getSheet(0), that.setting, -1);
+        me.workBook.focus(true);
+        me.currentComponent = [];
+        that.workBook.getSheet(0).setRowCount(5);
+        if(row < me.currentCache.length){
+            //标记当前工料机
+            me.currentGlj = me.currentCache[row];
+            if(allowComponent.includes(me.currentCache[row].gljType)){
+                //展示数据
+                if(me.currentGlj.component.length > 0){
+                    me.currentComponent = me.getCurrentComponent(me.currentGlj.component);
+                    if(me.currentComponent.length > 0){
+                        sheetOpr.showData(that.workBook.getSheet(0), that.setting, me.currentComponent);
                     }
                 }
             }
-            else{
-                me.currentGlj = null;
-            }
+        }
+        else{
+            me.currentGlj = null;
         }
     },
     onEnterCell: function (sender, args) {
@@ -374,19 +379,19 @@ let repositoryGljObj = {
                 let focusToCol;
                 function getFocusToCol (me){
                     if(!me.addGljObj[me.setting.header[0].dataCode]){
-                        $('#alertGljTxt').text('编号不能为空,继续增加工料机?');
+                        $('#alertGljTxt').text('编号不能为空,继续增加人材机?');
                         return 0;
                     }
                     else if(!me.addGljObj[me.setting.header[1].dataCode]){
-                        $('#alertGljTxt').text('名称不能为空,继续增加工料机?');
+                        $('#alertGljTxt').text('名称不能为空,继续增加人材机?');
                         return 1;
                     }
                     else if(!me.addGljObj[me.setting.header[3].dataCode]){
-                        $('#alertGljTxt').text('计量单位不能为空,继续增加工料机?');
+                        $('#alertGljTxt').text('计量单位不能为空,继续增加人材机?');
                         return 3;
                     }
                     else if(!me.addGljObj[me.setting.header[5].dataCode]){
-                        $('#alertGljTxt').text('类型不能为空,继续增加工料机?');
+                        $('#alertGljTxt').text('类型不能为空,继续增加人材机?');
                         return 5;
                     }
                     else {
@@ -579,103 +584,153 @@ let repositoryGljObj = {
             me.mixUpdateRequest(updateArr, addArr, []);
         }
     },
-    repositoryGljDelOpr: function () {
+    delGljs: function (sels) {
         let me = repositoryGljObj;
-        me.workBook.commandManager().register('repositoryGljDel', function () {
-            let sheet = me.workBook.getSheet(0),
-                updateArr = [], removeArr = [],
-                tempRemoveArr= [],
-                refGljCodes = [], //已被引用的工料机
-                updateBasePrcArr = [],//删除基价单位后重新计算
-                sels = sheet.getSelections(),
-                canUpdate = false,
-                cacheSection = me.currentCache;
-            if(sels.length > 0 && cacheSection.length > 0){
-                for(let i = 0; i < sels.length; i++){
-                    if(sels[i].colCount === me.setting.header.length){
-                        for(let j = 0; j < sels[i].rowCount; j++){
-                            if(sels[i].row + j < cacheSection.length){
-                                //删除了已被引用成组成物的工料机,重新计算所有引用此组成物的工料机的单价、组成物数组
-                                let updateGljs = me.getUpdateGljs(cacheSection[sels[i].row + j], true);
-                                if(updateGljs.updateArr.length > 0 || updateGljs.updateBasePrcArr.length > 0){
-                                    for(let i = 0; i < updateGljs.updateArr.length; i++){
-                                        updateArr.push(updateGljs.updateArr[i]);
-                                    }
-                                    for(let i = 0; i < updateGljs.updateBasePrcArr.length; i++){
-                                        updateBasePrcArr.push(updateGljs.updateBasePrcArr[i]);
-                                    }
+        let sheet = me.workBook.getSheet(0),
+            updateArr = [], removeArr = [],
+            tempRemoveArr= [],
+            refGljCodes = [], //已被引用的工料机
+            updateBasePrcArr = [],//删除基价单位后重新计算
+            canUpdate = false,
+            cacheSection = me.currentCache;
+        if(sels.length > 0 && cacheSection.length > 0){
+            for(let i = 0; i < sels.length; i++){
+                if(sels[i].colCount === me.setting.header.length){
+                    for(let j = 0; j < sels[i].rowCount; j++){
+                        if(sels[i].row + j < cacheSection.length){
+                            //删除了已被引用成组成物的工料机,重新计算所有引用此组成物的工料机的单价、组成物数组
+                            let updateGljs = me.getUpdateGljs(cacheSection[sels[i].row + j], true);
+                            if(updateGljs.updateArr.length > 0 || updateGljs.updateBasePrcArr.length > 0){
+                                for(let i = 0; i < updateGljs.updateArr.length; i++){
+                                    updateArr.push(updateGljs.updateArr[i]);
+                                }
+                                for(let i = 0; i < updateGljs.updateBasePrcArr.length; i++){
+                                    updateBasePrcArr.push(updateGljs.updateBasePrcArr[i]);
                                 }
-                                removeArr.push(cacheSection[sels[i].row + j].ID);
-                                //tempRemoveArr.push({ID: cacheSection[sels[i].row + j].ID, code: cacheSection[sels[i].row + j].code});
-                                //删除后重新计算引用了此工料机的定额单价
-                                updateBasePrcArr.push({gljId: cacheSection[sels[i].row + j].ID, gljType: cacheSection[sels[i].row + j].gljType, basePrice: 0, delete: 1});
                             }
+                            removeArr.push(cacheSection[sels[i].row + j].ID);
+                            //tempRemoveArr.push({ID: cacheSection[sels[i].row + j].ID, code: cacheSection[sels[i].row + j].code});
+                            //删除后重新计算引用了此工料机的定额单价
+                            updateBasePrcArr.push({gljId: cacheSection[sels[i].row + j].ID, gljType: cacheSection[sels[i].row + j].gljType, basePrice: 0, delete: 1});
                         }
                     }
-                    else{
-                        let maxCol = sels[i].col + sels[i].colCount - 1;
-                        if(sels[i].col >= 2 && maxCol <= 4){
-                            for(let j = 0; j < sels[i].rowCount; j++){
-                                if(sels[i].row + j < cacheSection.length){
-                                    let updateObj = cacheSection[sels[i].row + j];
-                                    for(let col = sels[i].col; col <= maxCol; col++){
-                                        if(me.setting.header[col].dataCode === 'basePrice'){
-                                            //如果类型不为混凝土、砂浆、配合比、机械,才可删除单价 basePrice = 0
-                                            if(!allowComponent.includes(updateObj.gljType)){
-                                                canUpdate = true;
-                                                updateObj[me.setting.header[col].dataCode] = 0;
-                                                updateBasePrcArr.push({gljId: updateObj.ID, gljType: updateObj.gljType, basePrice: 0});
-                                            }
-                                        }
-                                        else{
+                }
+                else{
+                    let maxCol = sels[i].col + sels[i].colCount - 1;
+                    if(sels[i].col >= 2 && maxCol <= 4){
+                        for(let j = 0; j < sels[i].rowCount; j++){
+                            if(sels[i].row + j < cacheSection.length){
+                                let updateObj = cacheSection[sels[i].row + j];
+                                for(let col = sels[i].col; col <= maxCol; col++){
+                                    if(me.setting.header[col].dataCode === 'basePrice'){
+                                        //如果类型不为混凝土、砂浆、配合比、机械,才可删除单价 basePrice = 0
+                                        if(!allowComponent.includes(updateObj.gljType)){
                                             canUpdate = true;
-                                            updateObj[me.setting.header[col].dataCode] = '';
+                                            updateObj[me.setting.header[col].dataCode] = 0;
+                                            updateBasePrcArr.push({gljId: updateObj.ID, gljType: updateObj.gljType, basePrice: 0});
                                         }
                                     }
-                                    if(canUpdate){
-                                        updateArr.push(updateObj);
+                                    else{
+                                        canUpdate = true;
+                                        updateObj[me.setting.header[col].dataCode] = '';
                                     }
                                 }
+                                if(canUpdate){
+                                    updateArr.push(updateObj);
+                                }
                             }
                         }
-                        //编号、名称、类型不可为空
-                        else{
-                            if(sels[i].row < cacheSection.length){
-                                let text = '', cantNullStr =['编码', '名称', '类型'];
-                                for(let col = sels[i].col; col <= sels[i].col + sels[i].colCount -1; col++){
-                                    if(cantNullStr.indexOf(me.setting.header[col].headerName) !== -1){
-                                        text += me.setting.header[col].headerName + " ";
-                                    }
+                    }
+                    //编号、名称、类型不可为空
+                    else{
+                        if(sels[i].row < cacheSection.length){
+                            let text = '', cantNullStr =['编码', '名称', '类型'];
+                            for(let col = sels[i].col; col <= sels[i].col + sels[i].colCount -1; col++){
+                                if(cantNullStr.indexOf(me.setting.header[col].headerName) !== -1){
+                                    text += me.setting.header[col].headerName + " ";
                                 }
-                                $('#alertText').text(text + "不可为空!");
-                                $('#codeAlertBtn').click();
-                                $('#codAleConfBtn').click(function () {
-                                });
-                                $('#codAleClose').click(function () {
-                                });
                             }
+                            $('#alertText').text(text + "不可为空!");
+                            $('#codeAlertBtn').click();
+                            $('#codAleConfBtn').click(function () {
+                            });
+                            $('#codAleClose').click(function () {
+                            });
                         }
                     }
                 }
-                if(removeArr.length > 0 || updateArr.length > 0){
-                    //删除警告
-                    $('#alertGljTxt').text('可能已有定额引用了当前工料机,导致定额查找不到此工料机。确定要删除吗?');
-                    $('#gljAlertBtn').click();
-                    //确认
-                    $('#aleConfBtn').click(function () {
-                        me.mixUpdateRequest(updateArr, [], removeArr);
-                        /*if(updateBasePrcArr.length > 0 && me.rationLibs.length > 0){
-                            me.updateRationBasePrcRq(updateBasePrcArr);
-                        }*/
-                    });
-                }
             }
-
+            if(removeArr.length > 0 || updateArr.length > 0){
+                //删除警告
+                $('#alertGljTxt').text('可能已有定额引用了当前工料机,导致定额查找不到此工料机。确定要删除吗?');
+                $('#gljAlertBtn').click();
+                //确认
+                $('#aleConfBtn').unbind('click');
+                $('#aleConfBtn').bind('click', function () {
+                    me.mixUpdateRequest(updateArr, [], removeArr);
+                    /*if(updateBasePrcArr.length > 0 && me.rationLibs.length > 0){
+                     me.updateRationBasePrcRq(updateBasePrcArr);
+                     }*/
+                });
+            }
+        }
+    },
+    repositoryGljDelOpr: function () {
+        let me = repositoryGljObj;
+        me.workBook.commandManager().register('repositoryGljDel', function () {
+            let sels = me.workBook.getActiveSheet().getSelections();
+            me.delGljs(sels);
         });
-
         me.workBook.commandManager().setShortcutKey(null, GC.Spread.Commands.Key.del, false, false, false, false);
         me.workBook.commandManager().setShortcutKey('repositoryGljDel', GC.Spread.Commands.Key.del, false, false, false, false);
     },
+    onContextmenuOpr: function () {
+        let me = repositoryGljObj;
+        $.contextMenu({
+            selector: '#GLJListSheet',
+            build: function($triggerElement, e){
+                //控制允许右键菜单在哪个位置出现
+                let sheet = me.workBook.getSheet(0);
+                let offset = $("#GLJListSheet").offset(),
+                    x = e.pageX - offset.left,
+                    y = e.pageY - offset.top;
+                let target = sheet.hitTest(x, y);
+                let sel = sheet.getSelections()[0];
+                if(sel.row === -1){
+                    sel.row = 0;
+                }
+                if(sel.col === -1){
+                    sel.col = 0;
+                }
+                if(target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){//在表格内
+                    me.initSel(target.row);
+                    if(sel.row > target.row || sel.row + sel.rowCount - 1 < target.row ||
+                        sel.col > target.col || sel.col + sel.colCount - 1 < target.col ){
+                        sheet.setActiveCell(target.row, target.col);
+                    }
+                    return {
+                        callback: function(){},
+                        items: {
+                            "delete": {
+                                name: "删除",
+                                disabled: function () {
+                                    return !(me.currentCache && me.currentCache[target.row]);
+                                },
+                                icon: "fa-remove",
+                                callback: function (key, opt) {
+                                    let curSel = _.cloneDeep(sheet.getSelections()[0]);
+                                    curSel.colCount = me.setting.header.length;
+                                    me.delGljs([curSel]);
+                                }}
+                        }
+                    };
+                }
+                else{
+                    return false;
+                }
+            }
+        });
+    },
     validUpdateObj: function (pasteObj, rowIdx) {
         let rst = {updateGlj: [], updateBasePrcArr: []}, backUpObj = {},
             me = repositoryGljObj,

+ 1 - 1
web/building_saas/complementary_ration_lib/html/dinge.html

@@ -498,8 +498,8 @@
                 </div>
             </div>
             <div class="modal-footer">
-                <button type="button"  class="btn btn-secondary" data-dismiss="modal">取消</button>
                 <a href="javascript:void(0);" id="gljSelY" class="btn btn-primary">确定</a>
+                <button type="button"  class="btn btn-secondary" data-dismiss="modal">取消</button>
             </div>
         </div>
     </div>

+ 32 - 26
web/building_saas/complementary_ration_lib/js/ration.js

@@ -70,33 +70,37 @@ let rationOprObj = {
     onSelectionChanged: function (sender, info) {
         if(info.oldSelections.length === 0 && info.newSelections.length > 0 || info.oldSelections[0].row !== info.newSelections[0].row){
             let row = info.newSelections[0].row;
-            let me = rationOprObj,
-                sheetGLJ = rationGLJOprObj.sheet, settingGLJ = rationGLJOprObj.setting,
-                sheetCoe = rationCoeOprObj.sheet, settingCoe = rationCoeOprObj.setting,
-                sheetAss = rationAssistOprObj.sheet, settingAss = rationAssistOprObj.setting,
-                sheetInst = rationInstObj.sheet, settingInst = rationInstObj.setting;
-            sheetCommonObj.cleanSheet(sheetGLJ, settingGLJ, -1);
-            sheetCommonObj.cleanSheet(sheetCoe, settingCoe, -1);
-            sheetCommonObj.cleanSheet(sheetAss, settingAss, -1);
-            sheetCommonObj.cleanSheet(sheetInst, settingInst, -1);
-            let cacheSection = me.getCache();
-            if (cacheSection && row < cacheSection.length) {
-                rationGLJOprObj.getGljItems(cacheSection[row], function () {
-                    me.workBook.focus(true);
-                });
-                rationCoeOprObj.getCoeItems(cacheSection[row], function () {
-                    me.workBook.focus(true);
-                });
-                rationAssistOprObj.getAssItems(cacheSection[row]);
-                rationInstObj.getInstItems(cacheSection[row], function () {
-                    me.workBook.focus(true);
-                });
-            }
-            else {
-                rationGLJOprObj.currentRationItem = null;
-            }
-            me.workBook.focus(true);
+            let me = rationOprObj;
+            me.rationSelInit(row);
+        }
+    },
+    rationSelInit: function (row) {
+        let me = rationOprObj,
+            sheetGLJ = rationGLJOprObj.sheet, settingGLJ = rationGLJOprObj.setting,
+            sheetCoe = rationCoeOprObj.sheet, settingCoe = rationCoeOprObj.setting,
+            sheetAss = rationAssistOprObj.sheet, settingAss = rationAssistOprObj.setting,
+            sheetInst = rationInstObj.sheet, settingInst = rationInstObj.setting;
+        sheetCommonObj.cleanSheet(sheetGLJ, settingGLJ, -1);
+        sheetCommonObj.cleanSheet(sheetCoe, settingCoe, -1);
+        sheetCommonObj.cleanSheet(sheetAss, settingAss, -1);
+        sheetCommonObj.cleanSheet(sheetInst, settingInst, -1);
+        let cacheSection = me.getCache();
+        if (cacheSection && row < cacheSection.length) {
+            rationGLJOprObj.getGljItems(cacheSection[row], function () {
+                me.workBook.focus(true);
+            });
+            rationCoeOprObj.getCoeItems(cacheSection[row], function () {
+                me.workBook.focus(true);
+            });
+            rationAssistOprObj.getAssItems(cacheSection[row]);
+            rationInstObj.getInstItems(cacheSection[row], function () {
+                me.workBook.focus(true);
+            });
+        }
+        else {
+            rationGLJOprObj.currentRationItem = null;
         }
+        me.workBook.focus(true);
     },
     isDef: function (v) {
         return v !== undefined && v !== null;
@@ -546,6 +550,8 @@ let rationOprObj = {
                     else if (a.code < b.code) rst = -1;
                     return rst;
                 });
+                let curRow = me.workBook.getActiveSheet().getActiveRowIndex();
+                me.rationSelInit(curRow);
                 //jobContent
                 if(jobContentOprObj ){
                     jobContentOprObj.currentRationItems = cacheSection;

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

@@ -99,4 +99,50 @@ legend.legend{
     border-color:transparent transparent #000 transparent;}
 .elf-options:hover{
     background-color: #CCCCCC;
+}
+
+.inline-div{
+    display:inline;
+}
+
+/*快捷切换单位工程*/
+
+
+
+
+
+/*.menu a:hover {
+    color: #fff;
+    background: #40DE5A;
+}*/
+
+
+.menu ul ul {
+    visibility: hidden;
+    position: absolute;
+    top: -1px;
+    left: 100px;
+}
+
+.menu ul li:hover ul, .menu ul a:hover ul {
+    visibility: visible;
+}
+
+.menu ul :hover ul ul {
+    visibility: hidden;
+}
+
+.menu ul :hover ul :hover ul {
+    visibility: visible;
+}
+
+.ui-datepicker-next, .ui-datepicker-next:hover{
+    background-image: url("/lib/jquery-ui/images/ui-icons_444444_256x240.png");
+    background-repeat: no-repeat;
+    background-position: -28px -12px;
+}
+.ui-datepicker-prev, .ui-datepicker-prev:hover{
+    background-image: url("/lib/jquery-ui/images/ui-icons_444444_256x240.png");
+    background-repeat: no-repeat;
+    background-position: -90px -12px;
 }

+ 77 - 18
web/building_saas/css/main.css

@@ -175,9 +175,10 @@ a{
 .bottom-tools {
     height: 30px;
     line-height: 30px;
-    background:#F1F1F1;
-    bottom:30px;
-    left:2px;
+    background:#fff;
+    bottom:20px;
+    left:22px;
+    z-index: 999
 }
 .side-tabs .nav-tabs .nav-item {
     z-index: 999
@@ -369,7 +370,10 @@ a{
     border-bottom:1px solid #ddd
 }
 .navbar-crumb span{
-    width: 200px
+    float:left;
+}
+.navbar-crumb span.text-truncate{
+    max-width: 200px;
 }
 .dropdown-item{
     color:#007bff
@@ -395,19 +399,74 @@ a{
 .custom-file-input:lang(zh) ~ .custom-file-label::after {
     content: "浏览";
 }
-/*.popover{position:absolute;
-    top:0;left:0;
-    z-index:1060;
-    display:block;
-    max-width:276px;
-    font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-style:normal;font-weight:400;line-height:1.5;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;white-space:normal;line-break:auto;font-size:.875rem;word-wrap:break-word;
-    background-color:black;
-    background-clip:padding-box;
-    border:1px solid black;
-    border-radius:.3rem}*/
+.custom-file-input{
+    cursor: pointer;
+}
 
-/*
-.arrow{
-    background-color:black;
+.message-box {
+    position:absolute;
+    background:#000;
+    padding:8px 10px;
+    line-height: 18px;
+    border-radius:4px;
+    text-align:center;
+    box-shadow:2px 2px 6px #ccc;
+    color:#fff;
+}
+.triangle-border {
+    position:absolute;
+    left:10px;
+    overflow:hidden;
+    width:0;
+    height:0;
+    border-width:6px;
+    border-style:solid dashed dashed dashed;
+}
+.tb-border {
+    bottom:-12px;
+    border-color:#000 transparent transparent transparent;
+}
+.tb-background {
+    bottom:-11px;
+    border-color:#000 transparent transparent transparent;
+}
+/*快捷切换单位工程*/
+.navbar-crumb{
+    position: relative;
+}
+.navbar-crumb .f-nav,.navbar-crumb .s-nav{
+    position: absolute;
+    z-index: 999;
+    width: 200px;
+    background:#fff;
+    border: 1px solid rgba(0,0,0,.15);
+    padding: .5rem 0;
 }
-*/
+.navbar-crumb .f-nav{
+    right:50px;
+    top:35px;
+}
+.navbar-crumb .s-nav{
+    left:200px
+}
+.navbar-crumb .f-nav li{
+    padding: .25rem 1rem;
+    cursor: default;
+}
+.navbar-crumb .f-nav li.focus{
+    color: #16181b;
+    background-color: #f7f7f9;
+}
+.navbar-crumb .f-nav li .s-nav{
+    display: none
+}
+.navbar-crumb .f-nav li.focus .s-nav{
+    display: block
+}
+.bottom-tools {
+    height: 30px;
+    line-height: 30px;
+    background:#F1F1F1;
+    bottom:30px;
+    left:2px;
+}

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

@@ -157,7 +157,7 @@
                 </div>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-primary" data-dismiss="modal" id="renameUnitFileConfirm" disabled>确定</button>
+                <button type="button" class="btn btn-primary" id="renameUnitFileConfirm">确定</button>
                 <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
             </div>
         </div>

+ 49 - 7
web/building_saas/main/html/main.html

@@ -31,8 +31,6 @@
         let userAccount = '<%- userAccount %>';
         let userID = '<%- userID %>';
         let projectReadOnly = JSON.parse('<%- projectReadOnly %>');
-        console.log(`projectReadOnly`);
-        console.log(projectReadOnly);
     </script>
 </head>
 
@@ -114,6 +112,9 @@
                           <li class="nav-item">
                               <a class="nav-link px-3" href="javascript:void(0)" id="stdRationTab" relaPanel="#de">定额库</a>
                           </li>
+<!--                          <li class="nav-item">
+                              <a class="nav-link px-3" href="javascript:void(0)" id="blockLibTab" relaPanel="#kmbk">块模板库</a>
+                          </li>-->
                       </ul>
                   </div>
               </div>
@@ -420,9 +421,9 @@
                                   </div>
                                   <div class="resize" id="qdResize" style="background: #F1F1F1"></div>
                                   <div class="bottom-content">
-                                      <div class="row" id="stdBillsJobTab">
-                                          <div class="col-lg-6 p-0" id="stdBillsJobs"></div>
-                                          <div class="col-lg-6 p-0" id="stdBillsFeatures"></div>
+                                      <div class="p-0" id="stdBillsJobTab">
+                                          <div class="p-0" style="width: 50%; float: left" id="stdBillsJobs"></div>
+                                          <div class="p-0" style="width: 50%; float: left" id="stdBillsFeatures"></div>
                                       </div>
                                       <div class="row" id="stdBillsRemarkTab">
                                           <div class="col-lg-12 p-0">
@@ -445,7 +446,24 @@
                                           </div>
                                           <!--搜索结果窗体-->
                                           <div class="side-search-box col-12 p-0" id="rationSearchResult" style="display: none;">
+                                              <div class="d-flex justify-content-between">
+                                                  <span id="rationSearchCount"></span>
+                                                  <a title="关闭搜索" class="btn btn-link btn-sm" href="javascript:void(0)"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                                              </div>
+                                              <div class="w-100 main-data-side-search"></div>
                                           </div>
+                                          <!--
+                                          html.push('<div class="d-flex justify-content-between">');
+        html.push('<span>搜索结果:');
+        html.push(result.length.toString());
+        html.push('</span>');
+        html.push('<a title="关闭搜索" class="btn btn-link btn-sm" href="javascript:void(0)"><i class="fa fa-remove" aria-hidden="true"></i></a>');
+        html.push('</div>');
+
+        html.push('<div class="w-100 main-data-side-search">');
+        html.push('</div>');
+        return html.join('');
+                                          -->
                                       </div>
                                   </div>
                                   <div class="top-content" style="overflow: hidden">
@@ -457,6 +475,26 @@
                                       <div class="main-data-bottom" id="stdSectionRations"></div>
                                   </div>
                               </div>
+                              <!--块模板库-->
+                              <div class="tab-pane" id="kmbk">
+                                  <div class="tools-bar-height-d container-fluid">
+                                      <div class="p-1 row">
+                                          <button id="btn_block_collapse" class="btn btn-primary btn-sm" type="button">展开/折叠</button>
+                                          <button id="btn_block_newFolder" class="btn btn-primary btn-sm" type="button">新建分类</button>
+                                          <button id="btn_block_newSubFolder" class="btn btn-warning btn-sm" type="button">新建子类</button>
+                                      </div>
+                                  </div>
+                                  <div class="top-content" style="background-color:#ff7e0e;overflow: hidden">
+                                      <div class="main-data-side-d" id="div_block_tree">
+                                      </div>
+                                  </div>
+                                  <div class="resize" id="kmbkResize" style="background: #F1F1F1"></div>
+                                  <div class="bottom-content" style="background-color:#50df89;">
+                                      <div class="main-data-bottom" id="div_block_detail">
+
+                                      </div>
+                                  </div>
+                              </div>
                           </div>
                       </div>
                   </div>
@@ -733,7 +771,7 @@
                                 </div>
                                 <!--系统选项-->
                                 <div class="tab-pane fade" id="system-setting" role="tabpanel">
-                                    <div class="modal-auto-height">
+                                    <div class="modal-auto-height" style="overflow: hidden">
                                         <fieldset class="form-group">
                                             <div class="form-check">
                                                 <label class="form-check-label">
@@ -748,6 +786,7 @@
                                                 </label>
                                             </div>
                                         </fieldset>
+                                            <label style="margin-top: 320px">将影响所有建设项目</label>
                                     </div>
                                 </div>
                             </div>
@@ -755,6 +794,7 @@
                     </div>
                 </div>
                 <div class="modal-footer">
+                    <a href="javascript:void(0);" class="btn btn-primary" id="property_default" data-dismiss="modal">恢复默认系统设置</a>
                     <a href="javascript:void(0);" class="btn btn-primary" id="property_ok" data-dismiss="modal">确定</a>
                     <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                 </div>
@@ -969,7 +1009,7 @@
                     </ul>
                     <div class="tab-content">
                         <div class="tab-pane active" id="m-js" role="tabpanel">
-                            <div class="form-group">
+                            <div class="form-group" id="expArea">
                                 <input class="form-control" id="calcBaseExp" value="">
                                 <p class="form-text">
                                     <button class="btn btn-secondary btn-sm" id="addOpr">+</button>
@@ -1547,10 +1587,12 @@
     <script type="text/javascript" src="/web/building_saas/main/js/main.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/controllers/project_controller.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/controllers/block_controller.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/controllers/material_controller.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/side_tools.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/std_billsGuidance_lib.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/std_bills_lib.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/std_ration_lib.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/views/block_lib.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/models/quantity_detail.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/glj_view_contextMenu.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/calc_program_view.js"></script>

+ 0 - 1
web/building_saas/main/js/controllers/block_controller.js

@@ -331,7 +331,6 @@ let BlockController = {
                 i==0?firstNode = temNode:'';
             }
         }
-
         ProjectController.syncDisplayNewNodes(projectObj.mainController, newNodes);
         let sels = projectObj.mainController.sheet.getSelections();
         //设置选中并更新下方显示

+ 154 - 0
web/building_saas/main/js/controllers/material_controller.js

@@ -0,0 +1,154 @@
+/**
+ * Created by zhang on 2018/9/12.
+ */
+let MaterialController = {
+    //规则相关映射
+    rule1: function (node) {
+        let itemText = node.data.itemCharacterText;
+        let name = this.getKeyString(itemText,"材质及规格:");
+        if(name){
+            return{name:name,specs:""}//规格型号变成空的
+        }
+        return null;
+    },
+    rule2:function (node) {
+        let itemText = node.data.itemCharacterText;
+        let name = this.getKeyString(itemText,"混凝土种类:");
+        let specs = this.getKeyString(itemText,"混凝土强度等级:");
+        if(name||specs){
+            let doc ={};
+            if(name) doc["name"] = name;
+            if(specs) doc["specs"] = specs;
+            return doc;
+        }
+        return null
+    },
+    replaceMaterial:function(nodes){
+        let me = this;
+        this.getMaterial(nodes,function (result) {
+            if(!_.isEmpty(result)){
+                me.startReplace(nodes,result);
+            }
+        });
+    },
+
+    startReplace:function (nodes,result) {//其实应该是批量修改工料机属性,与替换工料机不同
+        let me = this,updateData = [];
+        for(let n of nodes){
+            let code = n.data.code;
+            if(code.length >= 9){
+                let r_list = this.eachNode(n,result[code.substr(0,9)]);
+                if(r_list.length > 0) updateData.push(...r_list);
+            }
+        }
+        if(updateData.length == 0) return;
+        $.bootstrapLoading.start();
+        CommonAjax.post("/material/replace",updateData,function(result){
+            $.bootstrapLoading.end();
+            me.updateCacheAfterReplace(result)
+        })
+    },
+
+    updateCacheAfterReplace:function (result){
+        let nodes = [];
+        for(let data of result){
+            let node = projectObj.project.ration_glj.refreshRationNode(data.name,data.adjustState,data.rationID);//刷新定额名称和子目调整状态
+            if(node) nodes.push(node);
+            if(data.ration_gljs.length > 0) this.refreshRationGLJ(data.ration_gljs);
+        }
+        if(nodes.length >0){
+            projectObj.project.projectGLJ.loadData(function () {
+                projectObj.project.calcProgram.calcNodesAndSave(nodes,function(){
+                    installationFeeObj.calcInstallationFee();
+                });
+                gljOprObj.refreshView();
+            })
+        }
+    },
+    refreshRationGLJ:function(ration_gljs){
+        let ration_glj_model = projectObj.project.ration_glj;
+        for(let rg of ration_gljs){
+             let glj = ration_glj_model.refreshByID(rg.ID,rg.doc);
+            ration_glj_model.refreshTreeNodeIfNeeded(glj);//刷新造价书上的树节点(如果需要)
+        }
+    },
+
+    eachNode:function (node,item) {
+        let replaceDatas =[];
+        if(item && item.bills.rule){
+             let replace_property = this["rule"+item.bills.rule](node);//按清单设置的规则获取要修改的属性
+             if(replace_property){
+                 replaceDatas = this.getReplaceData(node.data.ID,item.materialMap,replace_property);
+             }
+        }
+        return replaceDatas;
+    },
+
+    getReplaceData:function (billsItemID,materialMap,replace_property) {
+        let list = [];
+        let replace_glj_list = this.findMatchRationGLJ(billsItemID,materialMap);//取出需要替换的工料机和对替换的材料内容
+        for(let r of replace_glj_list){
+            let doc = this.getDoc(r.glj,r.material,replace_property);//获取要修改的字段
+            list.push({glj:gljOprObj.setGLJPrice(r.glj),doc:doc});
+        }
+        return list;
+    },
+
+
+    getDoc:function (glj,material,replace_property) {//取定额工料机中需要修改的内容
+        let doc = {},keyList = ['name','specs','type','unit'];
+        for(let key of keyList){
+            if(glj[key] != material[key]) doc[key] = material[key];
+        }
+        for(let rkey in replace_property){
+            doc[rkey] = replace_property[rkey]
+        }
+        return doc;
+
+    },
+
+
+    findMatchRationGLJ:function (billsItemID,materialMap) {//查找清单下匹配的需要替换的定额工料机
+        let replaceList=[];
+        for(let g of projectObj.project.ration_glj.datas){
+            if(g.billsItemID == billsItemID && materialMap[g.original_code]) {
+                replaceList.push({glj:g,material:materialMap[g.original_code]});
+            }
+        }
+        return replaceList;
+    },
+    getMaterial:function (nodes,callback) {
+        let data = [],materialMap= null;
+        for(let n of nodes){
+            let code = n.data.code;
+            if(code.length >= 9 && n.data.billsLibId){
+                let billCode = code.substr(0,9);
+                data.push({code:billCode,billsLibId:n.data.billsLibId});
+            }
+        }
+        if(data.length>0){
+            //data 按编码去重
+            let dataMap = _.indexBy(data,'code');
+            CommonAjax.post("/material/getMaterial",dataMap,function (result) {
+                callback(result);
+            })
+        }else {
+            callback(null);
+        }
+    },
+
+    getKeyString:function (itemText,matchStr) {//截取关键数据
+        itemText = itemText.replace(/:/g, ":");//中文字符转换为英文字符
+        itemText = itemText.replace(matchStr,"@$@");//用特殊符号取代关键字,方便截取
+        let index = itemText.indexOf("@$@");
+        if(index == -1) return null;
+        let temString = itemText.substr(index+3);
+        let strArray =  temString.split(/\n/);
+        let keyString = this.trim(strArray[0]);
+        return keyString===""?null:keyString;
+    },
+    trim:function (str) {
+        return str.replace(/(^\s*)|(\s*$)/g, "");
+    }
+
+};

+ 8 - 5
web/building_saas/main/js/controllers/project_controller.js

@@ -29,15 +29,18 @@ ProjectController = {
                 }
                 return rst;
             });
+            let lastNode = null;
             for(let newNode of newNodes){
                 sc.sheet.addRows(newNode.serialNo(), 1);
-            }
-            for(let newNode of newNodes){
-                sc.setTreeSelected(newNode);
                 TREE_SHEET_HELPER.refreshTreeNodeData(sc.setting, sc.sheet, [newNode], false);
-                sc.sheet.setSelection(newNode.serialNo(), sels[0].col, 1, 1);
+                lastNode = newNode
                // sc.sheet.showRow(newNode.serialNo(), GC.Spread.Sheets.VerticalPosition.center);
             }
+            if(lastNode){
+                sc.setTreeSelected(lastNode);
+                sc.sheet.setSelection(lastNode.serialNo(), sels[0].col, 1, 1);
+            }
+
             cbTools.refreshFormulaNodes();
         });
     },
@@ -185,7 +188,7 @@ ProjectController = {
             if (selected.source.children.length > 0) {
                 alert('当前清单已有清单子项,不能套用定额。');
             } else if (selected.data.calcBase&&selected.data.calcBase!="") {
-                alert('当前有基数计算不能插入定额/量价/工料机。');
+                alert('当前有基数计算,不能插入定额/量价/人材机。');
             } else {
                 if(selected.data.type === billType.FB){
                     return;

+ 8 - 0
web/building_saas/main/js/main.js

@@ -67,6 +67,8 @@ function loadMainSize() {//加载造价书页面各高度
     });
 }
 
+let mouseMoveCount = 0;
+
 /**
  * 拖动更改div大小
  *
@@ -130,6 +132,12 @@ function slideResize(eles, limit, type, callback) {
                 eles.nearSpread[type](nEleChangeSize);
                 eles.farSpread[type](fEleChangeSize - navSize);
             }
+            //实时刷新页面
+            mouseMoveCount+=Math.abs(moveSize);//取移动的决对值
+            if(mouseMoveCount >=5){//当累计移动超过5个像素时,才刷新,减少刷新次数
+                if(callback) callback();
+                mouseMoveCount = 0;
+            }
         }
     });
 

+ 15 - 2
web/building_saas/main/js/models/calc_base.js

@@ -335,8 +335,12 @@ let cbTools = {
                 //基数是跟清单直接关联的
                 if(bases[i]['type'] === 'base' && cbTools.isDef(calcBase.baseFigures[bases[i]['value']])){
                     let figureMultiRef= calcBase.baseFigures[bases[i]['value']]['multiRef'];
+                    let cycleCalcRef = calcBase.baseFigures[bases[i]['value']]['cycleCalcRef'];
                     //重构后:
                     if(cbTools.isDef(figureMultiRef)){
+                        if(cbTools.isDef(cycleCalcRef)){
+                            figureMultiRef = cycleCalcRef;
+                        }
                         for(let flag of figureMultiRef){
                             let bills = cbTools.findBill(flag);
                             if(cbTools.isDef(bills)){
@@ -972,7 +976,7 @@ let baseFigureTemplate = {
         let projGljs = calcBase.project.projectGLJ.datas.gljList;
         for(let glj of projGljs){
             if(glj.type === gljType.MAIN_MATERIAL && glj.ratio_data.length === 0){
-                rst = (rst + parseFloat(glj.supply_quantity * glj.unit_price.market_price).toDecimal(decimalObj.bills.totalPrice)).toDecimal(decimalObj.bills.totalPrice);
+                rst = (rst + parseFloat(glj.supply_quantity * glj.unit_price.base_price).toDecimal(decimalObj.bills.totalPrice)).toDecimal(decimalObj.bills.totalPrice);
             }
         }
         return rst;
@@ -1057,7 +1061,7 @@ let baseFigureTemplate = {
         return rst;
     },
     'JDZCF': function (tender) {//甲定主材费
-        const quantityType = tender ? 'tenderQuantity' : 'quantity';
+       /* const quantityType = tender ? 'tenderQuantity' : 'quantity';
         let rst = 0;
         let projGljs = calcBase.project.projectGLJ.datas.gljList;
         for(let glj of projGljs){
@@ -1066,6 +1070,15 @@ let baseFigureTemplate = {
                 rst = (rst + parseFloat(glj[quantityType] * marketPrice).toDecimal(decimalObj.bills.totalPrice)).toDecimal(decimalObj.bills.totalPrice);
             }
         }
+        return rst;*/
+        const quantityType = tender ? 'tenderQuantity' : 'quantity';
+        let rst = 0;
+        let projGljs = calcBase.project.projectGLJ.datas.gljList;
+        for(let glj of projGljs){
+            if(glj.type === gljType.MAIN_MATERIAL && (glj.supply === supplyType.JDYG || glj.supply === supplyText.JDYG)){
+                rst = (rst + parseFloat(glj[quantityType] * glj.unit_price.base_price).toDecimal(decimalObj.bills.totalPrice)).toDecimal(decimalObj.bills.totalPrice);
+            }
+        }
         return rst;
     },
     'JDSBF': function (tender) {//甲定设备费

+ 21 - 12
web/building_saas/main/js/models/calc_program.js

@@ -365,10 +365,17 @@ let calcTools = {
         };
 
         if (priceType == priceTypes.ptDiffPrice){
-            if (gljTypes == baseMaterialTypes)
-                result = (temp - temp2).toDecimal(decimalObj.ration.unitPrice)
-            else
-                result = (temp.toDecimal(decimalObj.ration.unitPrice) - temp2.toDecimal(decimalObj.ration.unitPrice)).toDecimal(decimalObj.ration.unitPrice);
+            if (typeof isCQ2018 != 'undefined'){
+                // 如下这一句十分重要!JS计算误差导致379.08-331.695=47.38499999999999。如果直接取2位会变成47.38。所以先取6位47.385,再取2位47.39。
+                result = (temp - temp2).toDecimal(decimalObj.process);
+                result = result.toDecimal(decimalObj.ration.unitPrice)    // 重庆2018所有都是先汇总相减后再取舍
+            }
+            else{
+                if (gljTypes == baseMaterialTypes)
+                    result = (temp - temp2).toDecimal(decimalObj.ration.unitPrice)
+                else
+                    result = (temp.toDecimal(decimalObj.ration.unitPrice) - temp2.toDecimal(decimalObj.ration.unitPrice)).toDecimal(decimalObj.ration.unitPrice);
+            };
         }
         else{
             result = result.toDecimal(decimalObj.ration.unitPrice);
@@ -383,7 +390,7 @@ let calcTools = {
         for (let glj of gljArr) {
             if (baseMachineMasterTypes.includes(glj.type)){
                 // 机型不符
-                if ((masterTypeFilter.length > 0) && (glj.model && !masterTypeFilter.includes(glj.model))) break;
+                if ((masterTypeFilter.length > 0) && (glj.model && !masterTypeFilter.includes(glj.model))) continue;
 
                 let gljQ;
                 if (isTender){
@@ -404,9 +411,10 @@ let calcTools = {
                         mdSum = (mdSum).toDecimal(decimalObj.glj.unitPriceHasMix);
                     }
                 }
-                // result = result + (gljQ * mdSum).toDecimal(decimalObj.process);
-                result = result + (gljQ * mdSum).toDecimal(decimalObj.ration.unitPrice);
-                result = (result).toDecimal(decimalObj.ration.unitPrice);
+                if (typeof isCQ2018 != 'undefined')
+                    result = (result + (gljQ * mdSum).toDecimal(decimalObj.process)).toDecimal(decimalObj.process)
+                else
+                    result = (result + (gljQ * mdSum).toDecimal(decimalObj.ration.unitPrice)).toDecimal(decimalObj.ration.unitPrice);
             }
         }
         result = (result).toDecimal(decimalObj.ration.unitPrice);
@@ -879,13 +887,14 @@ let calcTools = {
                 let gljQ;
                 if (isTender){
                     calcTools.calcGLJTenderQty(node, glj);
-                    gljQ = glj.tenderQuantity;
+                    gljQ = glj.tenderQuantity.toDecimal(decimalObj.glj.quantity);
                 }
                 else
-                    gljQ = glj.quantity;
+                    gljQ = glj.quantity.toDecimal(decimalObj.glj.quantity);
 
-                rst = rst + (gljQ * calcTools.uiNodeQty(node)).toDecimal(decimalObj.process);
-                rst = rst.toDecimal(decimalObj.process);
+                // rst = rst + (gljQ * calcTools.uiNodeQty(node)).toDecimal(decimalObj.process);
+                // rst = rst.toDecimal(decimalObj.process);
+                rst = (rst + gljQ).toDecimal(decimalObj.process);
             }
         };
         return rst.toDecimal(decimalObj.glj.quantity);

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

@@ -451,7 +451,7 @@ var Ration = {
                 if (selected.source.children.length > 0) {
                     alert('当前清单已有清单子项,不能套用定额。');
                 } else if (selected.data.calcBase&&selected.data.calcBase!="") {
-                    alert('当前有基数计算不能插入定额/量价/工料机。');
+                    alert('当前有基数计算,不能插入定额/量价/人材机。');
                 } else {
                     if(selected.data.type === billType.FB){
                         return;
@@ -561,7 +561,7 @@ var Ration = {
                 else if (selected.source.children.length > 0) {
                     alert('当前清单已有清单子项,不能套用定额。');
                 } else if (selected.data.calcBase&&selected.data.calcBase!="") {
-                    alert('当前有基数计算不能插入定额/量价/工料机。');
+                    alert('当前有基数计算,不能插入定额/量价/人材机。');
                 } else {
                     billItemID = selected.source.getID();
                     nextID = selected.tree.rootID();
@@ -641,7 +641,7 @@ var Ration = {
                 else if (selected.source.children.length > 0) {
                     alert('当前清单已有清单子项,不能套用定额。');
                 } else if (selected.data.calcBase&&selected.data.calcBase!="") {
-                    alert('当前有基数计算不能插入定额/量价/工料机。');
+                    alert('当前有基数计算,不能插入定额/量价/人材机。');
                 } else {
                     billItemID = selected.source.getID();
                     nextID = selected.tree.rootID();

+ 20 - 19
web/building_saas/main/js/models/ration_glj.js

@@ -242,18 +242,19 @@ let ration_glj = {
             this.reCalcWhenGLJChange({rationID:rationID});
         };
         ration_glj.prototype.refreshEachItme = function (doc, query) {
+            let glj = this.refreshByID(query.ID,doc);
+            return glj.rationID;
+        };
+
+        ration_glj.prototype.refreshByID=function (ID,doc) {
             let glj_list = projectObj.project.ration_glj.datas;
-            let glj_index = _.findIndex(glj_list, (glj) => {
-                return glj.ID == query.ID;
-            })
-            /*var sheet_index= _.findIndex(gljOprObj.sheetData,(sd)=>{
-             return sd.ID==query.ID;
-             })*/
+            let glj_index = _.findIndex(glj_list,{"ID":ID});
             _.forEach(doc, function (n, key) {
                 glj_list[glj_index][key] = n;
             });
-            return glj_list[glj_index].rationID;
+            return glj_list[glj_index]
         };
+
         ration_glj.prototype.refreshAfterDelete = function (data) {
             let me = projectObj.project.ration_glj;
             let glj_list = me.datas;
@@ -476,22 +477,22 @@ let ration_glj = {
         };
         ration_glj.prototype.refreshRationAfterEdit= function(data,rationID,rnode){
             let nodes = [];
+            let node = this.refreshRationNode(data.name,data.adjustState,rationID);
+            if (node) nodes.push(node);
+            if (rnode)  nodes.push(rnode);
+            projectObj.mainController.refreshTreeNode(nodes);
+        };
+        ration_glj.prototype.refreshRationNode = function(name,adjustState,rationID){
             let node = projectObj.project.mainTree.findNode(rationID);
-            if (node) {
-                if(data.adjustState){
-                    node.data.adjustState = data.adjustState;
-                }
-                if(data.name){
-                    node.data.name = data.name;
-                }
-                nodes.push(node);
+            if (!node)  return null;
+            if(gljUtil.isDef(adjustState)){
+                node.data.adjustState = adjustState;
             }
-            if (rnode) {
-                nodes.push(rnode);
+            if(gljUtil.isDef(name)){
+                node.data.name = name;
             }
-            projectObj.mainController.refreshTreeNode(nodes);
+           return node
         };
-
         ration_glj.prototype.getGLJData = function (cb) {
             let engineerID = projectInfoObj.projectInfo.property.engineering_id;
             CommonAjax.get('/rationGlj/getGLJData/'+engineerID, function (data) {

+ 186 - 0
web/building_saas/main/js/views/block_lib.js

@@ -0,0 +1,186 @@
+/**
+ * Created by CSL on 2018-09-19.
+ */
+var blockLibObj = {
+    datas: [],
+    mainSpread: null,
+    mainSheet: null,
+    mainSetting: {
+        header:[
+            {headerName:"名称",headerWidth:400,dataCode:"name", dataType: "String"}
+        ],
+        view:{
+            comboBox:[],
+            lockColumns:[],
+            colHeaderHeight: CP_Col_Width.colHeader,
+            rowHeaderWidth: CP_Col_Width.rowHeader
+        }
+    },
+    buildSheet: function (){
+        let me = this;
+        me.datas = [];
+        if (me.mainSpread) {
+            me.mainSpread.destroy();
+            me.mainSpread = null;
+        };
+
+        me.mainSpread = sheetCommonObj.buildSheet($('#div_block_tree')[0], me.mainSetting, me.datas.length);
+        sheetCommonObj.spreadDefaultStyle(me.mainSpread);
+        me.mainSheet = me.mainSpread.getSheet(0);
+        // sheetCommonObj.showData(me.mainSheet, me.mainSetting, me.datas);
+    },
+    showData: function () {
+        let me = this;
+        let sheet =me.mainSheet;
+        let cols = me.mainSetting.header;
+        let datas = me.datas;
+        let fuc = function () {
+            sheet.setRowCount(datas.length);
+            me.initTree(true);
+            // sheet.setFormatter(-1, 1, '@');
+            for(let col = 0, cLen = cols.length; col < cLen; col++){
+                // sheet.getRange(-1, col, -1, 1).hAlign(GC.Spread.Sheets.HorizontalAlign[cols[col]['hAlign']]);
+                // sheet.getRange(-1, col, -1, 1).vAlign(GC.Spread.Sheets.VerticalAlign[cols[col]['vAlign']]);
+                for(let row = 0, rLen = datas.length; row < rLen; row++){
+                    sheet.setValue(row, col, datas[row][cols[col]['dataCode']]);
+                }
+            }
+        };
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        fuc();
+        sheet.resumePaint();
+        sheet.resumeEvent();
+    },
+    initTree: function (collapse) {
+        let me = this;
+        me.mainSheet.getRange(-1, 0, -1, 1).cellType(me.getTreeNodeCellType(me.datas));
+        for(let i =0, len = me.datas.length; i < len; i++){
+            if(me.datas[i].hasOwnProperty('items')){
+                let collapsed = false;
+                if(collapse){
+                    me.datas[i].collapsed = false;
+                    collapsed = true;
+                }else {
+                    collapsed = me.datas[i].collapsed == undefined ? true : me.datas[i].collapsed;
+                }
+            }
+        }
+    },
+    getTreeNodeCellType: function (data) {
+        var ns = GC.Spread.Sheets;
+        var rectW = 10;
+        var rectH = 10;
+        var margin = 3;
+        function TreeNodeCellType() {
+        }
+
+        function drowRect(ctx,x,y,w,h) {///
+            ctx.save();
+            ctx.strokeStyle = "gray";
+            ctx.translate(0.5,0.5);
+            ctx.beginPath();
+            var rectX = x+margin;
+            var rectY =  y+ Math.round(h/2)-rectH/2;
+            ctx.moveTo(rectX, rectY);
+            ctx.lineTo(rectX, rectY+rectH);
+            ctx.lineTo(rectX+rectW, rectY+rectH);
+            ctx.lineTo(rectX+rectW, rectY);
+            ctx.lineTo(rectX, rectY);
+            ctx.moveTo(rectX+rectW, y+Math.round(h/2));
+            ctx.lineTo(rectX+rectW+5, y+Math.round(h/2));
+            ctx.stroke();
+            ctx.restore();
+        }
+
+        function drowSymbol(ctx,x,y,w,h,collapsed) {
+            ctx.save();
+            ctx.strokeStyle = "#000000";
+            ctx.translate(0.5, 0.5);
+            ctx.beginPath();
+            ctx.moveTo(x+margin+2, y+Math.round(h/2));
+            ctx.lineTo(x+margin+8, y+Math.round(h/2));
+            var rectY =  y+ Math.round(h/2)-rectH/2;
+            if(collapsed){
+                ctx.moveTo(x+margin+rectW/2,rectY+2);
+                ctx.lineTo(x+margin+rectW/2,rectY+2+6);
+            }
+            ctx.stroke();
+            ctx.restore();
+        }
+
+        function drowSubItem(ctx,x,y,w,h,offset,nextItem) {
+            offset+=6;
+            ctx.save();
+            ctx.strokeStyle = "gray";
+            ctx.translate(0.5, 0.5);
+            ctx.beginPath();
+            ctx.moveTo(x+offset, y);
+            ctx.lineTo(x+offset, y+Math.round(h/2));
+            offset+=9;
+            ctx.lineTo(x+offset, y+Math.round(h/2));
+            if(nextItem&&!nextItem.hasOwnProperty('items')){
+                ctx.moveTo(x+offset-9, y+Math.round(h/2));
+                ctx.lineTo(x+offset-9, y+h);
+            }
+            ctx.stroke();
+            ctx.restore();
+            return offset;
+        }
+
+        TreeNodeCellType.prototype = new ns.CellTypes.Text();
+        TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            if(value!=null){
+                var offset = margin+rectW+6;
+                var recode = data[options.row];
+                if(recode&&recode.hasOwnProperty('items')){
+                    drowRect(ctx,x,y,w,h);
+                    var collapsed = recode.collapsed==undefined?true:recode.collapsed;//options.sheet.getTag(options.row,options.col);
+                    drowSymbol(ctx,x,y,w,h,collapsed);
+                }else if(recode&&!recode.hasOwnProperty('items')){
+                    offset= drowSubItem(ctx,x,y,w,h,offset,data[options.row+1]);
+                    offset+=1;
+                }
+                arguments[2] = x + offset;
+                arguments[4] = w - offset;
+                GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
+
+            }
+        };
+        TreeNodeCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+            return {
+                x: x,
+                y: y,
+                row: context.row,
+                col: context.col,
+                cellStyle: cellStyle,
+                cellRect: cellRect,
+                sheetArea: context.sheetArea
+            };
+        }
+        TreeNodeCellType.prototype.processMouseDown = function (hitinfo) {
+            var recode = data[hitinfo.row];
+            if(recode&&recode.hasOwnProperty('items')){
+                var hoffset= hitinfo.cellRect.x+3;
+                if (hitinfo.x > hoffset && hitinfo.x < hoffset + 10){
+                    var collapsed = recode.collapsed==undefined?true:recode.collapsed;
+                    collapsed = !collapsed
+                    recode.collapsed=collapsed;
+                    //hitinfo.sheet.setTag(hitinfo.row,hitinfo.col,collapsed);
+                    hitinfo.sheet.getRange(hitinfo.row+1, -1, recode.items.length, -1).visible(!collapsed);
+                    hitinfo.sheet.invalidateLayout();
+                    hitinfo.sheet.repaint();
+                }
+            }
+        };
+        return new TreeNodeCellType();
+    }
+};
+
+$(document).ready(function(){
+/*    if (!blockLibObj.mainSpread){
+        blockLibObj.buildSheet();
+        blockLibObj.showData();
+    }*/
+
+});

+ 56 - 6
web/building_saas/main/js/views/calc_base_view.js

@@ -175,6 +175,7 @@ let calcBaseView = {
     initCalctor: function (type) {//type = bills、ration
         let me = calcBaseView;
         let showDatas;
+        me.inputExpr = $('#calcBaseExp');
         me.curType = type;
         if (type === me.type.bills) {
             //锁定的清单不显示
@@ -183,11 +184,10 @@ let calcBaseView = {
             }
             //显示清单基数分类
             $('#cbClassList').show();
-           // $('#qd-jsjs .modal-content').css('width', '670px');
             $('#cbRowDiv').addClass('row');
             $('#billsBaseSpread').addClass('col-9');
-            //
-            let node = projectObj.project.mainTree.selected;
+            let row = projectObj.mainSpread.getActiveSheet().getActiveRowIndex();
+            let node = projectObj.project.mainTree.items[row];
             //输入框显示原本的
             if (me.isDef(node.data.calcBase)) {
                 me.inputExpr.val(cbParser.toFExpr(node.data.calcBase));
@@ -203,7 +203,6 @@ let calcBaseView = {
             //$('#qd-jsjs .modal-content').css('width', '');
             $('#cbRowDiv').removeClass('row');
             $('#billsBaseSpread').removeClass('col-9');
-
             let calcItem = calcProgramManage.getSelectionInfo().calcItem;
             if (calcItem.dispExprUser) {
                 me.inputExpr.val(calcItem.dispExpr);
@@ -296,7 +295,7 @@ let calcBaseView = {
             if(me.curType === me.type.bills){
                 let selected = projectObj.project.mainTree.selected;
                 projectObj.updateCellValue(selected, me.getInputExpr(), {data: {field: 'calcBase'}});
-                if(projectObj.project.calcBase.success){
+                if(projectObj.project.calcBase.success || selected.data.calcBase === me.getInputExpr()){
                     //$('#qd-jsjs').modal('hide');
                     $('#calcBaseFeeRate').modal('hide');
                 }
@@ -390,7 +389,7 @@ let calcBaseView = {
                 sheetArea: context.sheetArea
             };
         };
-        CalcBaseCellType.prototype.processMouseDown = function (hitinfo) {
+        /*CalcBaseCellType.prototype.processMouseDown = function (hitinfo) {
             let me=calcBaseView;
             me.pmLeave = false;
             if(me.editingCell==null){
@@ -428,6 +427,57 @@ let calcBaseView = {
                 hitinfo.sheet.repaint();
                 calcBaseView.pmLeave = true;
             }
+        };*/
+        CalcBaseCellType.prototype.processMouseDown = function (hitinfo) {
+            let me = calcBaseView;
+            if(me.editingCell && hitinfo.row==me.editingCell.row){
+                var offset=hitinfo.cellRect.x+hitinfo.cellRect.width-6;
+                var imageMagin=3;
+                var imageHeight = hitinfo.cellRect.height-2*imageMagin;
+                var imageWidth = hitinfo.cellRect.width*2/7;
+                if(hitinfo.x<offset&&hitinfo.x>offset-imageWidth){
+                    if(!projectReadOnly && me.ifEdit(type, hitinfo.row)){
+                        hitinfo.sheet.setActiveCell(hitinfo.row, hitinfo.col);
+                        if(hitinfo.sheet.getParent() === projectObj.mainSpread){
+                            projectObj.project.mainTree.selected = projectObj.project.mainTree.items[hitinfo.row] ? projectObj.project.mainTree.items[hitinfo.row] : null;
+                        }
+                        calcBaseView.confirmBtn.attr('toggle', 'calcBase');
+                        changeCalcBaseFeeRate('calcBase');
+                        $('#tabCalcBase').tab('show');
+                        calcBaseView.initCalctor(type);
+                    }
+                }else {//鼠标点击其它地方,消失
+                    hideButton(hitinfo);
+                }
+            }
+        };
+        CalcBaseCellType.prototype.processMouseEnter = function (hitinfo){
+            let me = calcBaseView;
+            me.pmLeave = false;
+            if(me.editingCell==null){
+                var showSelectBtn = true;
+                showSelectBtn=me.ifEdit(type, hitinfo.row);
+                if(showSelectBtn){
+                    me.editingCell={
+                        row:hitinfo.row,
+                        col:hitinfo.col
+                    };
+                    hitinfo.sheet.invalidateLayout();
+                    hitinfo.sheet.repaint();
+                }
+            }
+        };
+        CalcBaseCellType.prototype.processMouseLeave = function (hitinfo) {
+            hideButton(hitinfo);
+        };
+
+        function hideButton(hitinfo) {
+            if(!calcBaseView.pmLeave){
+                calcBaseView.editingCell=null;
+                hitinfo.sheet.invalidateLayout();
+                hitinfo.sheet.repaint();
+                calcBaseView.pmLeave = true;
+            }
         }
         return new CalcBaseCellType();
     },

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

@@ -106,6 +106,7 @@ let ConfirmModal = {
                 datas.push({'code': std.code, 'name': std.name, 'unit': unit});
             }
             SheetDataHelper.loadSheetData(this.setting, sheet, datas);
+            this.spread.getActiveSheet().setActiveCell(0, 0);
             this.modalObj.modal('show');  
             ConfirmModal.stdBillsUnit.spread.refresh();  
         }

+ 20 - 11
web/building_saas/main/js/views/fee_rate_view.js

@@ -201,12 +201,12 @@ var feeRateObject={
         let rates = projectObj.project.FeeRate.getActivateFeeRate().rates;
         let rowIdx = 0, pID = 0;
         if (fID){
+            fID = parseInt(fID);
             rowIdx = _.findIndex(rates,{ID:fID});
-            pID = rates[rowIdx].ParentID;
+            if(rowIdx != -1) pID = rates[rowIdx].ParentID;
         }
         // 费率现有可能有多层节点,所以要递归展开父节点
-        expandParent(pID,rates,sheet);
-
+        if(pID) expandParent(pID,rates,sheet);
         sheet.setSelection(rowIdx, -1, 1, -1);
         sheet.showRow(rowIdx, GC.Spread.Sheets.VerticalPosition.center);
         feeRateObject.onCellClick({type: 'CellClick'}, {row:rowIdx});
@@ -708,13 +708,21 @@ var feeRateObject={
         }
     },
     submitSaveAs:function (newName) {
-        var me = this;
-          projectObj.project.FeeRate.feeRateFileSaveAs(newName,function (result) {
-              me.activateFeeRate = result;
-              me.loadPageContent();
-              $('#copy-lv').modal('hide');
-              socket.emit('feeRateChangeNotify', projectObj.project.FeeRate.getActivateFeeRateFileID());
-              $.bootstrapLoading.end();
+        let me = this;
+        let FeeRate = projectObj.project.FeeRate;
+        FeeRate.feeRateFileSaveAs(newName,function (result) {
+            me.activateFeeRate = result;
+            me.loadPageContent();
+            $('#copy-lv').modal('hide');
+            let data ={
+                projectID:projectObj.project.ID(),
+                oldRoom:socketObject.roomInfo.feeRate,
+                newRoom: FeeRate.getActivateFeeRateFileID(),
+                name:'feeRate'
+            };
+            socket.emit('changeNewRoom',data);
+            socketObject.roomInfo.feeRate = FeeRate.getActivateFeeRateFileID();
+            $.bootstrapLoading.end();
         });
 
     },
@@ -820,9 +828,10 @@ var feeRateObject={
     submitFeeRateFromBill:function () {
        var rate = feeRateObject.feeRateSelection;
        var selected = projectObj.project.mainTree.selected;
+       if(selected.data.feeRateID === parseInt(rate.ID)) return $("#calcBaseFeeRate").modal('hide');
         $.bootstrapLoading.start();
         projectObj.project.FeeRate.submitFeeRateFromBill(rate,selected.data,function (data) {
-            selected.data.feeRateID=rate.ID.toString();
+            selected.data.feeRateID= parseInt(rate.ID);
             selected.data.feeRate=scMathUtil.roundToString(rate.rate,getDecimal("feeRate"));
             selected.changed = true;
             projectObj.project.calcProgram.calcAndSave(selected);

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

@@ -404,6 +404,7 @@ var gljOprObj = {
     rationGLJEditCheck:function (args) {//true 可以编辑,false 不能编辑
         var me = gljOprObj;
         var header = me.setting.header;
+        if(me.sheet.getTag(args.row,args.col)=="locked") return false;//如果是双击树节点编号里设置了锁定标记,不能编辑
         if (_.includes(me.setting.view.lockColumns, args.col))  return false;//如果是锁定的列,不能编辑
         if(me.sheetData[args.row] != undefined){
             if(me.sheetData[args.row].isMixRatio){//对于组成物列
@@ -1277,6 +1278,7 @@ var gljOprObj = {
         let margin = 3;
 
         function TreeNodeCellType() {
+            this.ctx = null;
         }
         function drowRect(ctx, x, y, w, h) {
             ctx.save();
@@ -1328,9 +1330,9 @@ var gljOprObj = {
             ctx.restore();
             return offset;
         }
-
         TreeNodeCellType.prototype =  comboboxOptions?sheetCommonObj.getDynamicCombo():new ns.CellTypes.Text();
         TreeNodeCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            this.ctx= ctx;
             if (style.backColor) {//先画背景色
                 ctx.save();
                 ctx.fillStyle = style.backColor;
@@ -1387,8 +1389,13 @@ var gljOprObj = {
                     return;
                 }
             }
-            GC.Spread.Sheets.CellTypes.ComboBox.prototype.processMouseDown.apply(this, arguments);
-           // GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
+            if(comboboxOptions&&hitinfo.x > hitinfo.cellRect.x+hitinfo.cellRect.width -15){//点击了下拉框按钮,这里要判断下拉框是否会被挡住,从而决定是否自动调整滚动条
+                hitinfo.sheet.setTag(hitinfo.row,hitinfo.col,"");
+                sheetCommonObj.scrollSheetForOption(hitinfo.sheet,this.ctx,hitinfo.cellRect,hitinfo.row,comboboxOptions);//下拉框超出显示后自动调整滚动条
+                GC.Spread.Sheets.CellTypes.ComboBox.prototype.processMouseDown.apply(this, arguments);
+            }else {
+                hitinfo.sheet.setTag(hitinfo.row,hitinfo.col,"locked")//通过这个来控制除了点击下拉框的三角形,点击其它地方不充许进入编辑状态,不然不好控制下拉框超出页面后调整滚动条
+            }
         };
         let cellType = new TreeNodeCellType();
         if(comboboxOptions){
@@ -1404,12 +1411,12 @@ var gljOprObj = {
         }else {
             hasCom = this.hasComposition(node.data);
         }
-        return hasCom|| node.data.isEstimate == 1;
+        return hasCom;//2018-9-14 需求变更暂估工料机也能修改市场价原语句:return hasCom|| node.data.isEstimate == 1
     },
     locateZTree: function(ID) {
         let zTree = $.fn.zTree.getZTreeObj("gljTree");
         let node = null;
-        if (ID) node = zTree.getNodesByParam('ID', ID, null)[0]
+        if (ID) node = zTree.getNodesByParam('ID', ID, null)[0];
         if (!node) node = zTree.getNodeByTId('gljTree_1');
         zTree.selectNode(node);
         gljOprObj.gljCurTypeId = ID;

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

@@ -389,6 +389,7 @@ const importBills = (function(){
                     programID: null,
                     unit: rData[colMapping.unit] && rData[colMapping.unit]['value'] ? _deESC(rData[colMapping.unit]['value']) : '',
                     quantity: rData[colMapping.quantity] && rData[colMapping.quantity]['value'] ? _deESC(rData[colMapping.quantity]['value']) : '',
+                    quantityEXP: rData[colMapping.quantity] && rData[colMapping.quantity]['value'] ? _deESC(rData[colMapping.quantity]['value']) : '',
                     //安全文明
                     flags: flag === fixedFlag.CONSTRUCTION_ORGANIZATION && (rData[colMapping.name] && (rData[colMapping.name]['value'] === '安全文明施工专项费用' || rData[colMapping.name]['value'] === '安全文明施工费')) ?
                         [{fieldName: 'fixed', flag: fixedFlag.SAFETY_CONSTRUCTION}] : [],

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

@@ -54,8 +54,8 @@ let MainTreeCol = {
             else
                 rst = isDef(node.data.code) ? node.data.code : '';
 
-/*            if (node.data.adjustState && rst != '')
-                rst = rst + rationPrefix.replace;*/
+            if (node.data.adjustState && rst != '')
+                rst = rst + rationPrefix.replace;
             return rst;
         },
         marketPrice:function (node) {

+ 18 - 16
web/building_saas/main/js/views/project_glj_view.js

@@ -1208,19 +1208,20 @@ $(function () {
             // 从其他项目中复制
             changeUnitPriceId = $("#other-file").val();
             let newName = $("#other-file").children("option:selected").text();
-            let currentOption = _.find(projectGljObject.changeInfo.self,{name:newName});
-            if(currentOption){ //存在则说明有重名的文件
-                //rename-unitFile
-                $("#rename-unitFile").modal({show:true});
-                $("#newUnitFileID").val(changeUnitPriceId);
-                $("#newUnitFileName").val(newName);
-                return;
-            }
+            projectObj.project.projectGLJ.checkUnitFileName(newName,function (need_rename) {
+                if(need_rename){
+                    $("#rename-unitFile").modal({show:true});
+                    $("#newUnitFileID").val(changeUnitPriceId);
+                    $("#newUnitFileName").val(newName);
+                }else {
+                    let data = {project_id: scUrlUtil.GetQueryString('project'), change_id: changeUnitPriceId, type: type};
+                    projectObj.project.projectGLJ.changeFile(data,function () {
+                        projectGljObject.changeFileCallback();
+                    })
+                }
+            });
         }
-        let data = {project_id: scUrlUtil.GetQueryString('project'), change_id: changeUnitPriceId, type: type};
-        projectObj.project.projectGLJ.changeFile(data,function () {
-            projectGljObject.changeFileCallback();
-        })
+
     });
     // 单价文件选项切换
     $("input[name='change-type']").change(function () {
@@ -1261,10 +1262,10 @@ $(function () {
         projectGLJ.checkUnitFileName(this.value,function (data) {
             if(data){
                 $("#renameError_unitFile").text('已存在同名单价文件').show();
-                $('#renameUnitFileConfirm').attr("disabled","disabled");
+                //$('#renameUnitFileConfirm').attr("disabled","disabled");
             }else {
                 $("#renameError_unitFile").hide();
-                $('#renameUnitFileConfirm').removeAttr("disabled");
+               // $('#renameUnitFileConfirm').removeAttr("disabled");
             }
         });
 
@@ -1276,10 +1277,11 @@ $(function () {
         projectGLJ.checkUnitFileName(newName,function (data) {
             if(data){
                 $("#renameError_unitFile").text('已存在同名单价文件').show();
-                $('#renameUnitFileConfirm').attr("disabled","disabled");
+                //$('#renameUnitFileConfirm').attr("disabled","disabled");
             }else {
                 $("#renameError_unitFile").hide();
-                $('#renameUnitFileConfirm').removeAttr("disabled");
+                $('#rename-unitFile').modal('hide');
+               // $('#renameUnitFileConfirm').removeAttr("disabled");
                 let data = {project_id: scUrlUtil.GetQueryString('project'), change_id: changeUnitPriceId, type: 1,newName:newName};
                 projectObj.project.projectGLJ.changeFile(data,function () {
                     projectGljObject.changeFileCallback();

+ 156 - 36
web/building_saas/main/js/views/project_view.js

@@ -48,7 +48,7 @@ var projectObj = {
     },
     refreshBaseActn: function (tree) {
         let setButtonValid = function (valid, btn) {
-            if (valid) {
+            if (!projectReadOnly && valid) {
                 btn.removeClass('disabled');
             } else {
                 btn.addClass('disabled');
@@ -234,7 +234,7 @@ var projectObj = {
         let fieldCol = colSettingObj.getColByField(field);
         if(fieldCol){
             if(moveScroll){
-                mainSheet.showColumn(fieldCol, GC.Spread.Sheets.HorizontalPosition.left);
+                mainSheet.showColumn(fieldCol, GC.Spread.Sheets.HorizontalPosition.center);
             }
             mainSheet.setActiveCell(projectObj.project.mainTree.selected.serialNo(), fieldCol);
         }
@@ -540,6 +540,7 @@ var projectObj = {
             if (isDef(node.data.prefix) && node.data.prefix !== rationPrefix.none){
                  value = value.replace(new RegExp(node.data.prefix), '');
             };
+            value = value.replace(new RegExp(rationPrefix.replace), '');
             info.sheet.setValue(info.row, info.col, value);
         }
         if(node&&fieldName =='quantity'&&(node.data.quantityEXP !==null||node.data.quantityEXP !==undefined)){
@@ -581,15 +582,33 @@ var projectObj = {
         }
         if(node.sourceType == ModuleNames.ration){ //在定额编码中双击,如果右侧定额库没有展开,则自动展开。
             if(!rationLibObj.tree){
+                sessionStorage.setItem('stdRationLib', node.data.libID);
                 rationLibObj.doAfterGetRationTree = function () {
-                    this.locateAtRation(code);
+                    this.locateAtRation(node.data.libID, code);
                     this.doAfterGetRationTree = null;
                 };
             }
             else {
-                rationLibObj.locateAtRation(code);
+                if($('#stdRationLibSelect').select().val() != node.data.libID){
+                    let libOpts = $('#stdRationLibSelect').find('option');
+                    for(let libOpt of libOpts){
+                        if($(libOpt).val() == node.data.libID){
+                            $(libOpt).prop('selected', 'selected');
+                            break;
+                        }
+                    }
+                    $('#stdRationLibSelect').change();
+                    rationLibObj.doAfterGetRationTree = function () {
+                        this.locateAtRation(node.data.libID, code);
+                        this.doAfterGetRationTree = null;
+                    };
+                }
+                else {
+                    rationLibObj.locateAtRation(node.data.libID, code);
+                }
             }
             if(!$("#de").is(":visible"))  $('#stdRationTab').click();
+            console.log($('#stdRationLibSelect').select().val());
         }
 
     },
@@ -641,7 +660,17 @@ var projectObj = {
             function getPasteTextArr(info) {
                 let copyText = info.pasteData.text.trim();
                 if (!copyText) return null;
-                let rows = copyText.split('\r\n');
+                let spliter = '';
+                if (copyText.includes('\r\n')){
+                    spliter = '\r\n'
+                }
+                else if (copyText.includes('\n')){      // 兼容Unix、Mac 等系统回车换行符
+                    spliter = '\n'
+                }
+                else{
+                    spliter = '\r'
+                };
+                let rows = copyText.split(spliter);
                 let rstArr = [];
                 for (let row of rows) {
                     row = row.trim();
@@ -662,7 +691,7 @@ var projectObj = {
                         curNode = projectObj.project.mainTree.items[i - 1];
                         break;
                     }
-                };
+                }
 
                 if (nodesArr.length < count){
                     if (projectObj.project.mainTree.selected != curNode)
@@ -708,7 +737,7 @@ var projectObj = {
                         // 编号去掉“换、借、补”等多余的字
                         code = code.replace(new RegExp(rationPrefix.complementary), '');
                         code = code.replace(new RegExp(rationPrefix.borrow), '');
-                        // code = code.replace(new RegExp(rationPrefix.replace), '');
+                        code = code.replace(new RegExp(rationPrefix.replace), '');
                         updateRationCodes.push({'node':ptNode, value:code});
                     }
                     projectObj.project.Ration.updateRationCodes(updateRationCodes);
@@ -771,7 +800,7 @@ var projectObj = {
             for (let changedCell of changedObj.changedCells) {
                 let node = project.mainTree.items[changedCell.row];
                 let colSetting = setting.cols[changedCell.col];
-                let value = projectObj.checkSpreadEditingText(changedCell.text, colSetting)
+                let value = projectObj.checkSpreadEditingText(changedCell.text, colSetting);
                 if(colSetting.data.field=='code' && node.sourceType == project.Ration.getSourceType()&&node.data.type==rationType.ration){//如果是更新定额的编码
                     updateRationCodes.push({'node':node,value:value});
                 }else {
@@ -1087,6 +1116,7 @@ var projectObj = {
         var project = this.project, spread = this.mainSpread, controller = this.mainController;
         $.contextMenu({
             selector: '#billsSpread',
+            selectableSubMenu: true,
             build: function ($trigger, e) {
                 var target = SheetDataHelper.safeRightClickSelection($trigger, e, spread);
                 controller.setTreeSelected(controller.tree.items[target.row]);
@@ -1187,7 +1217,7 @@ var projectObj = {
                     callback: function (key, opt) {
                         if(project.mainTree.selected.data.type == billType.DXFY){
                             if(project.mainTree.selected.data.calcBase&&project.mainTree.selected.data.calcBase!=""){
-                                alert("当前有基数计算不能插入子项。");
+                                alert("当前有基数计算,不能插入子项。");
                                 return;
                             }
                         }
@@ -1231,13 +1261,16 @@ var projectObj = {
                     callback: function (key, opt) {
                         project.Ration.addNewRation(null,rationType.volumePrice,null,true);
                        // ProjectController.addRation(project, controller, rationType.volumePrice);
-                    }/*,
-                    visible: function(key, opt){
-                        var selected = project.mainTree.selected;
-                        if(selected){
-                           return canInsertRationNode(selected);
+                    },
+                  /*  items:{
+                        firstCommand:{
+                            name: "插入量价",
+                            icon: 'fa-sign-in',
+                            callback:function(key){
+
+                            }
                         }
-                       return false;
+
                     }*/
                 },
                 "insertGLJ": {
@@ -1253,7 +1286,7 @@ var projectObj = {
                         if(selected.sourceType == ModuleNames.bills){
                             if(selected.data.type == billType.FX||selected.data.type ==billType.BILL){
                                 if(selected.data.calcBase&&selected.data.calcBase!=""){
-                                    alert("当前有基数计算不能插入子项。");
+                                    alert("当前有基数计算,不能插入子项。");
                                     return;
                                 }
                             }
@@ -1383,6 +1416,17 @@ var projectObj = {
                             projectObj.editContent(node,'claimVisa');
                         }
                     }
+                },
+                "replaceMaterial":{
+                    name:'智能材料替换',
+                    icon: 'fa-edit',
+                    disabled:function (key,opt) {
+                        let  selected = project.mainTree.selected;
+                        return selected.sourceType==ModuleNames.bills ?!(project.Bills.isFXorBX(selected)||selected.source.children.length ==0):true//是分项、补项或叶子清单才有效;
+                    },
+                    callback:function(){
+                        MaterialController.replaceMaterial([project.mainTree.selected]);
+                    }
                 }
             }
         });
@@ -1405,6 +1449,7 @@ var projectObj = {
         col = parseInt(col);
         const sheet = this.mainSpread.getActiveSheet();
         sheet.setSelection(row, col, 1, 1);
+        row=row<this.mainController.tree.items.length?row:0;
         this.mainController.setTreeSelected(this.mainController.tree.items[row]);//触发树节点选中事件
         sheet.showRow(row, GC.Spread.Sheets.VerticalPosition.center);
     },
@@ -1693,10 +1738,12 @@ var projectObj = {
         });
     },
     ifItemCharHiden:function (setting) {//项目特征及内容列是否隐藏
-        let col = _.find(setting.cols,function (item) {
-            return  item.data.field == "itemCharacterText";
-        })
-        return !col.visible;
+        if(this.itemCol == null||this.itemCol == undefined){
+            this.itemCol = _.find(setting.cols,function (item) {
+                return  item.data.field == "itemCharacterText";
+            })
+        }
+        return !this.itemCol.visible;
     },
     //综合合价cellType
     getCommonTotalFeeCellType:function () {
@@ -1742,7 +1789,7 @@ var projectObj = {
                 sheetArea: context.sheetArea
             };
         };
-        CommonTotalFeeCellType.prototype.processMouseDown = function (hitinfo) {
+        /*CommonTotalFeeCellType.prototype.processMouseDown = function (hitinfo) {
             let me=calcBaseView;
             me.pmLeave = false;
             if(me.editingCell==null){
@@ -1781,6 +1828,58 @@ var projectObj = {
                 hitinfo.sheet.repaint();
                 calcBaseView.pmLeave = true;
             }
+        };*/
+        CommonTotalFeeCellType.prototype.processMouseDown = function (hitinfo) {
+            let me = calcBaseView;
+            if(me.editingCell && hitinfo.row==me.editingCell.row){
+                var offset=hitinfo.cellRect.x+hitinfo.cellRect.width-6;
+                var imageMagin=3;
+                var imageHeight = hitinfo.cellRect.height-2*imageMagin;
+                var imageWidth = hitinfo.cellRect.width*2/7;
+                if(hitinfo.x<offset&&hitinfo.x>offset-imageWidth){
+                    if(!projectReadOnly && me.ifEdit(type, hitinfo.row)){
+                        if(hitinfo.sheet.getParent() === projectObj.mainSpread){
+                            projectObj.project.mainTree.selected = projectObj.project.mainTree.items[hitinfo.row] ? projectObj.project.mainTree.items[hitinfo.row] : null;
+                        }
+                        hitinfo.sheet.setActiveCell(hitinfo.row, hitinfo.col);
+                        calcBaseView.confirmBtn.attr('toggle', 'commonTotalFee');
+                        changeCalcBaseFeeRate('commonTotalFee');
+                        $('#tabCalcBase').tab('show');
+                        calcBaseView.initCalctor(type);
+                        feeRateObject.showSelectModal(hitinfo);
+                    }
+                }else {//鼠标点击其它地方,消失
+                    hideButton(hitinfo);
+                }
+            }
+        };
+        CommonTotalFeeCellType.prototype.processMouseEnter = function (hitinfo){
+            let me = calcBaseView;
+            me.pmLeave = false;
+            if(me.editingCell==null){
+                var showSelectBtn = true;
+                showSelectBtn=me.ifEdit(type, hitinfo.row);
+                if(showSelectBtn){
+                    me.editingCell={
+                        row:hitinfo.row,
+                        col:hitinfo.col
+                    };
+                    hitinfo.sheet.invalidateLayout();
+                    hitinfo.sheet.repaint();
+                }
+            }
+        };
+        CommonTotalFeeCellType.prototype.processMouseLeave = function (hitinfo) {
+            hideButton(hitinfo);
+        };
+
+        function hideButton(hitinfo) {
+            if(!calcBaseView.pmLeave){
+                calcBaseView.editingCell=null;
+                hitinfo.sheet.invalidateLayout();
+                hitinfo.sheet.repaint();
+                calcBaseView.pmLeave = true;
+            }
         }
         return new CommonTotalFeeCellType();
     },
@@ -2036,6 +2135,14 @@ $('#recColSetting').click(function () {
     });
 });
 
+//恢复默认系统设置
+$('#property_default').click(function () {
+    let project = projectObj.project,
+        projectID = project.ID();
+    CommonAjax.post('/pm/api/defaultSettings', {user_id: userID, projectID: projectID}, function (rstData) {
+        window.location.href = `/main?project=${projectID}`;
+    });
+});
 $('#property_ok').click(function () {
     let project = projectObj.project,
         projectID = project.ID(),
@@ -2448,7 +2555,7 @@ $('#importConfirm').click(function () {
         //选择的表及导入位置
         let importSheetsInfo = importBills.getImportSheetsInfo();
         if(importSheetsInfo.length === 0){
-            throw '请选要导入的表';
+            throw '请选要导入的表';
         }
         let importSheets = importBills.getImportSheets(importJson.sheets, importSheetsInfo, fileType);
         console.log(`importSheets`);
@@ -2663,16 +2770,17 @@ $(function () {
 //项目只读,处理不可操作的工具栏
 function disableTools(){
     //造价书按钮
-    $('#insertRation').remove();
-    $('#delete').remove();
-    $('#upLevel').remove();
-    $('#downLevel').remove();
-    $('#upMove').remove();
-    $('#downMove').remove();
-    $('#ZLFB_btn').remove();
-    $('#switchTznr').remove();
-    $('#importSpan').remove();
-    $('a[name="lockBills"]').remove();
+    $('#insertRation').addClass('disabled');
+    $('#delete').addClass('disabled');
+    $('#upLevel').addClass('disabled');
+    $('#downLevel').addClass('disabled');
+    $('#upMove').addClass('disabled');
+    $('#downMove').addClass('disabled');
+    $('#ZLFB_btn').addClass('disabled');
+    $('#switchTznr').addClass('disabled');
+    $('#uploadLj').addClass('disabled');
+    $('#uploadGld').addClass('disabled');
+    $('a[name="lockBills"]').addClass('disabled');
     //关于计算
     $('#poj-settings-4').find('input').prop('disabled', 'disabled');
     //小数位数
@@ -2755,6 +2863,9 @@ function changeCalcBaseFeeRate(toggle) {
         $('#calcBaseFeeRate').find('.modal-title').text('计算基数选择').show();
         $('#calcBaseFeeRate').find('.modal-body').find('button:first').hide();
         $('#calcBaseFeeRate').find('.modal-body').find('ul:first').hide();
+        $('#calcBaseExp').remove();
+        let $input = $('<input>').attr('id', 'calcBaseExp').addClass('form-control');
+        $('#expArea').prepend($input);
     }
     else if(toggle === 'feeRate'){
         $('#calcBaseFeeRate').find('.modal-header').show();
@@ -2766,6 +2877,9 @@ function changeCalcBaseFeeRate(toggle) {
         $('#calcBaseFeeRate').find('.modal-header').hide();
         $('#calcBaseFeeRate').find('.modal-body').find('button:first').show();
         $('#calcBaseFeeRate').find('.modal-body').find('ul:first').show();
+        $('#calcBaseExp').remove();
+        let $textarea = $('<textarea>').attr('id', 'calcBaseExp').prop('rows', 3).addClass('form-control').css('resize', 'none');
+        $('#expArea').prepend($textarea);
     }
 }
 //综合合价弹出计算基数费率确认
@@ -2783,13 +2897,19 @@ $('#calcBaseFeeRateConf').click(function () {
         selected.data.userCalcBase = calcBaseValue;
         projectObj.project.calcBase.calculate(selected);
     }
-    if(!projectObj.project.calcBase.success){
-        return;
-    }
     if(validateFeeRate){
         feeRateObject.submitFeeRateFromBill();
     }
-    else if(!validateFeeRate && needToSave) {
+    else {
+        if(calcBaseValue === calcBaseValue){
+            $('#calcBaseFeeRate').modal('hide');
+        }
+    }
+    if(!projectObj.project.calcBase.success){
+        return;
+    }
+    else if((!validateFeeRate || selected.data.feeRateID === parseInt(feeRateObject.feeRateSelection.ID)) && needToSave) {
         projectObj.project.calcProgram.calcAndSave(selected);
+        $('#calcBaseFeeRate').modal('hide');
     }
 });

+ 45 - 5
web/building_saas/main/js/views/quantity_edit_view.js

@@ -41,11 +41,19 @@ let quantityEditObj = {
     },
     onCellDoubleClick:function (e,info) {
         if(quantityEditObj.datas[info.row]){
-            let oldVal = $("#quantityEXPValue").val();
-            $("#quantityEXPValue").val(oldVal+quantityEditObj.datas[info.row].code);
             $("#quantityEXPValue").focus();
+            quantityEditObj.setToQuantityEXP(quantityEditObj.datas[info.row].code);
+            quantityEditObj.spread.focus(false);
         }
     },
+    setToQuantityEXP:function (value) {
+        let oldVal = $("#quantityEXPValue").val();
+        let startIndex = getCursor($("#quantityEXPValue")[0]);//取光标位置
+        let strartString = oldVal.substring(0,startIndex);
+        let endString = oldVal.substring(startIndex);
+        $("#quantityEXPValue").val(strartString+value+endString);
+        setCursor($("#quantityEXPValue")[0],startIndex+value.length);//设置回光标位置
+    },
     getQuantityEditCellType:function () {
         var ns = GC.Spread.Sheets;
         function QuantityEditCellType() {
@@ -248,14 +256,15 @@ let quantityEditObj = {
 };
 $(function(){
     $('#quantityEXPEdit').on('shown.bs.modal', function (e) {
+        projectObj.mainSpread.focus(false);
         quantityEditObj.initSpread();
+        $("#quantityEXPValue").focus();
     });
 
     $('#operation_p').children("button").bind('click',function (){
-        let oldVal = $("#quantityEXPValue").val();
-        $("#quantityEXPValue").val(oldVal+$(this).text());
+        quantityEditObj.setToQuantityEXP($(this).text());
         $("#quantityEXPValue").focus();
-    })
+    });
 
     $("#quantityEditConf").bind('click',function () {
         let selected = projectObj.project.mainTree.selected;
@@ -264,6 +273,37 @@ $(function(){
             $("#quantityEXPEdit").modal('hide');
         }
     })
+    $('#quantityEXPEdit').bind('keypress', function (event) {
+        if(event.keyCode === 13){
+            $("#quantityEditConf").click();
+            event.preventDefault();
+        }
 
+    });
 
 });
+
+function getCursor(elem) {
+    //IE 9 ,10,其他浏览器
+    if (elem.selectionStart !== undefined) {
+        return elem.selectionStart;
+    } else { //IE 6,7,8
+        var range = document.selection.createRange();
+        range.moveStart("character", -elem.value.length);
+        var len = range.text.length;
+        return len;
+    }
+}
+
+function setCursor(elem, index) {
+    //IE 9 ,10,其他浏览器
+    if (elem.selectionStart !== undefined) {
+        elem.selectionStart = index;
+        elem.selectionEnd = index;
+    } else { //IE 6,7,8
+        var range = elem.createTextRange();
+        range.moveStart("character", -elem.value.length); //左边界移动到起点
+        range.move("character", index); //光标放到index位置
+        range.select();
+    }
+}

+ 132 - 56
web/building_saas/main/js/views/std_billsGuidance_lib.js

@@ -292,7 +292,7 @@ const billsGuidance = (function () {
                     data: {
                         field: "name",
                         vAlign: 1,
-                        hAlign: 1,
+                        hAlign: 0,
                         font: "Arial"
                     }
                 },
@@ -544,7 +544,6 @@ const billsGuidance = (function () {
             return;
         }
         bills.tree.selected = node;
-        refreshInsertRation();
         if(!node.elf.tree){
             CommonAjax.post('/billsGuidance/api/getItemsByBills', {guidanceLibID: libSel.val(), billsID: node.getID()}, function (rstData) {
                 //定额数据删除编号信息
@@ -562,26 +561,54 @@ const billsGuidance = (function () {
                 let firstLevelDatas = _.filter(rstData, function (data) {
                     return data.ParentID == -1;
                 });
-                //初始数据的选项显示请选择
+                //第一层初始数据的选项显示
                 for(let fData of firstLevelDatas){
                     let options = getOptions(fData, rstData);
-                    fData.options = options.length > 0 ? '请选择' : '';
+                    fData.options = options.length > 0 ? options[0].name : '';
+                    //下挂的选项
+                    fData.optionsData = options && options.length > 0 ? _.cloneDeep(options) : [];
+                    fData.optionChecked = options && options.length > 0 ? [_.cloneDeep(options[0])] : [];
                 }
-                initTree(node.elf, elfSheet, elfItem.treeSetting, firstLevelDatas);
+                renderSheetFunc(elfSheet, function () {
+                    initTree(node.elf, elfSheet, elfItem.treeSetting, firstLevelDatas);
+                    //初始选择选项
+                    let initOptsOpr = [];
+                    for(let elfNode of node.elf.tree.items){
+                        if(elfNode.data.optionsData.length > 0){
+                            initOptsOpr.push({node: elfNode, data: elfNode.data.optionsData[0]});
+                        }
+                    }
+                    for(let opr of initOptsOpr){
+                        insertNodeByData(opr.node, opr.data);
+                    }
+                    TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.elf.tree.items, false);
+                    setOptionsCellType(node.elf.tree.items);
+                    //项目指引初始焦点
+                    elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0);
+                    refreshInsertRation();
+                });
+            });
+        }
+        else{
+            renderSheetFunc(elfSheet, function () {
+                node.elf.controller.showTreeData();
                 setOptionsCellType(node.elf.tree.items);
-                //elfSheet.getRange(-1, 1, -1, 1).cellType(getOptionsCellType(null, null, null));
-                //setItemCellType(node.guidance.tree.items);
                 //项目指引初始焦点
                 elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0);
+                refreshInsertRation();
             });
         }
-        else{
-            node.elf.controller.showTreeData();
-            //elfSheet.getRange(-1, 1, -1, 1).cellType(getOptionsCellType(null, null, null));
-            setOptionsCellType(node.elf.tree.items);
-            //项目指引初始焦点
-            elfItemInitSel(elfSheet.getActiveRowIndex() ? elfSheet.getActiveRowIndex() : 0);
+    }
+    //获取选项的深度
+    //@param {Object}opt {Array}options(当前清单所有选项) @return {Array}
+    function getOptionDepth(opt, options) {
+        let parent = _.find(options, {ID: opt.ParentID});
+        let depth = 0;
+        while (parent){
+            depth++;
+            parent = _.find(options, {ID: parent.ParentID});
         }
+        return depth;
     }
     //获取施工工序含有的选项(即当前施工工序的子项),获取的顺序按照NextSiblingID排序
     //@param {Object}process {Array}datas @return {Array}
@@ -630,7 +657,7 @@ const billsGuidance = (function () {
     function setOptionsCellType(nodes) {
         let elfSheet = elfItem.workBook.getActiveSheet();
         for(let node of nodes){
-            if(node.data.options !== ''){
+            if(node.data.optionsData && node.data.optionsData.length > 0){
                 elfSheet.getCell(node.serialNo(), 1).locked(false).cellType(getOptionsCellType());
             }
             else {
@@ -638,6 +665,61 @@ const billsGuidance = (function () {
             }
         }
     }
+    //递归插入节点:原始项目指引数据奇数层为需要插入的节点,偶数层为下拉选项
+    //@param {Object}node(当前操作的节点) {Object}data(选项) @return {void}
+    function insertNodeByData(node, data) {
+        let elfSheet = elfItem.workBook.getActiveSheet();
+        let sameDepthNodes = node.children;
+        let insertNextSiblingID = -1,
+            insertParentID = node.data.ID;
+        //当前操作节点的选项
+        let nodeOpts = getOptions(node.data, bills.tree.selected.elf.datas);
+        let subOpts = getOptions(data, bills.tree.selected.elf.datas);
+        let dataDepth = getOptionDepth(data, bills.tree.selected.elf.datas);
+        if(subOpts.length >0 && subOpts[0].type !== itemType.ration){
+            if((dataDepth + 1) % 2 === 0){
+                //排序后的数据
+                let dataWithRank = _.find(nodeOpts, {ID: data.ID});
+                //确定插入位置
+                for(let subOpt of subOpts){
+                    for(let subNode of sameDepthNodes){
+                        //同层节点原本选项数据
+                        let subNodeOptData = _.find(bills.tree.selected.elf.datas, {ID: subNode.data.ID});
+                        //同层节点原本父选项数据
+                        let subNodeOptParent = _.find(bills.tree.selected.elf.datas, {ID: subNodeOptData.ParentID});
+                        let subNodeOptParentWithRank = _.find(nodeOpts, {ID: subNodeOptParent.ID});
+                        //父项顺序决定插入位置
+                        if(dataWithRank.rank < subNodeOptParentWithRank.rank){
+                            insertNextSiblingID = subNode.data.ID;
+                            break;
+                        }
+                        //父项顺序相同,根据子项顺序决定插入位置
+                        else if(dataWithRank.rank = subNodeOptParentWithRank.rank){
+                            if(subOpt.rank < subNode.data.rank){
+                                insertNextSiblingID = subNode.data.ID;
+                                break;
+                            }
+                        }
+                    }
+                    let sub2Opts = getOptions(subOpt, bills.tree.selected.elf.datas);
+                    subOpt.options = sub2Opts.length > 0 ? sub2Opts[0].name : '';
+                    let cloneOpt = _.cloneDeep(subOpt);//不改变原本的数据,比如ParentID
+                    cloneOpt.optionChecked = sub2Opts.length > 0 ? [_.cloneDeep(sub2Opts[0])] : [];
+                    cloneOpt.optionsData = sub2Opts.length > 0 ? _.cloneDeep(sub2Opts) : [];
+                    let newNode = node.tree.insertByData(cloneOpt, insertParentID, insertNextSiblingID);
+                    elfSheet.addRows(newNode.serialNo(), 1);
+                    node.tree.selected = newNode;
+                    elfSheet.setSelection(newNode.serialNo(), elfSheet.getSelections()[0].col, 1, 1);
+                    if(sub2Opts.length > 0 && sub2Opts[0].type !== itemType.ration){
+                        insertNodeByData(newNode, sub2Opts[0]);
+                    }
+                }
+            }
+            else {
+                insertNodeByData(node, subOpts[0]);
+            }
+        }
+    }
     //获取选项下拉多选单元格
     //@param {void} @return {void}
     function getOptionsCellType() {
@@ -654,8 +736,8 @@ const billsGuidance = (function () {
             let height = cellRect.height;
             let htmlArr = [];
             let options = getOptions(node.data, bills.tree.selected.elf.datas);
-            let optionsTitle = node.data.options.split(';').join('\n');
-            htmlArr.push(`<div title="${optionsTitle}" style="height: ${height}px; background: ${cellStyle.backColor};overflow: hidden; white-space: nowrap; text-overflow: ellipsis">${node.data.options}</div><div style="background: ${cellStyle.backColor};border: 1px solid; overflow: auto; height: ${options.length > 6 ? height*6 : height*options.length+5}px; font-size: 0.9rem;">`);
+            //let optionsTitle = node.data.options.split(';').join('\n');
+            htmlArr.push(`<div style="height: ${height}px; background: ${cellStyle.backColor};overflow: hidden; white-space: nowrap; text-overflow: ellipsis">${node.data.options}</div><div style="background: ${cellStyle.backColor};border: 1px solid; overflow: auto; height: ${options.length > 6 ? height*6 : height*options.length+5}px; font-size: 0.9rem;">`);
             for(let opt of options){
                 htmlArr.push(`<div title="${opt.name ? opt.name : ''}" class="elf-options" style="height: ${height}px;overflow: hidden; white-space: nowrap; text-overflow: ellipsis">
                         <input rank="${opt.rank}" value="${opt.ID}" style="margin-left: 5px; vertical-align: middle" type="checkbox" 
@@ -675,70 +757,56 @@ const billsGuidance = (function () {
                 checkedNameArr.push(opt.name);
                 optionChecked.push(opt);
             }
-            this.displayText = checkedNameArr.length > 0 ? checkedNameArr.join(';') : '请选择';
+            this.displayText = checkedNameArr.length > 0 ? checkedNameArr.join(';') : '';
             node.data.options = this.displayText;
             node.data.optionChecked = optionChecked;
             //删除节点
-            let deleteInfo = getDeleteInfo(node, optionChecked);
-            for(let dInfo of deleteInfo){
-                if(node.tree.delete(dInfo.node)){
-                    elfSheet.deleteRows(dInfo.deleteRow, dInfo.deleteCount);
-                }
+            let deleteNodes = getDeleteNodes(node, optionChecked);
+            for(let dNode of deleteNodes){
+                elfSheet.deleteRows(dNode.serialNo(), dNode.posterityCount() + 1);
+                node.tree.delete(dNode);
             }
             //插入节点
             for(let perCheked of optionChecked){
                 let exist = false;
+                let subOpts = getOptions(perCheked, bills.tree.selected.elf.datas);
                 for(let subNode of node.children){
-                    if(subNode.data.ID === perCheked.ID){
-                        exist = true;
+                    for(let subOpt of subOpts){
+                        if(subNode.data.ID === subOpt.ID){
+                            exist = true;
+                            break;
+                        }
                     }
                 }
                 //不重复且不为定额时插入
                 if(!exist && perCheked.type !== itemType.ration){
-                    insertNodeByData(node, perCheked);
+                    insertNodeByData(node, perCheked);//这里递归,默认第一个
                 }
             }
             TREE_SHEET_HELPER.refreshTreeNodeData(elfItem.treeSetting, elfSheet, node.tree.items, false);
             setOptionsCellType(node.tree.items);
             refreshInsertRation();
         }
-        //获取删除节点信息
-        function getDeleteInfo(node, optionChecked) {
+        //获取删除节点
+        function getDeleteNodes(node, optionChecked) {
             let rst = [];
             for(let subNode of node.children){
                 let exist = false;
                 for(let perChecked of optionChecked){
-                    if(subNode.data.ID === perChecked.ID){
-                        exist = true;
+                    let subOpts = getOptions(perChecked, bills.tree.selected.elf.datas);
+                    for(let subOpt of subOpts){
+                        if(subNode.data.ID === subOpt.ID){
+                            exist = true;
+                            break;
+                        }
                     }
                 }
                 if(!exist){
-                    let deleteRow = subNode.serialNo(),
-                        deleteCount = subNode.posterityCount() + 1;
-                    rst.push({node: subNode, deleteRow: deleteRow, deleteCount: deleteCount});
+                    rst.push(subNode);
                 }
             }
             return rst;
         }
-        //插入单个节点,node:当前操作的节点
-        function insertNodeByData(node, data) {
-            let sameDepthNodes = node.children;
-            let insertNextSiblingID = -1,
-                insertParentID = node.data.ID;
-            data.options = getOptions(data, bills.tree.selected.elf.datas).length > 0 ? '请选择' : '';
-            //确定插入位置
-            for(let subNode of sameDepthNodes){
-                if(data.rank < subNode.data.rank){
-                   insertNextSiblingID = subNode.data.ID;
-                   break;
-                }
-            }
-            let newNode = node.tree.insertByData(data, insertParentID, insertNextSiblingID);
-            elfSheet.addRows(newNode.serialNo(), 1);
-            node.tree.selected = newNode;
-            elfSheet.setSelection(newNode.serialNo(), elfSheet.getSelections()[0].col, 1, 1);
-
-        }
         OptionsCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();
 
         OptionsCellType.prototype.createEditorElement = function (context) {
@@ -951,16 +1019,24 @@ const billsGuidance = (function () {
         }
         if(!bills.tree.selected.elf){
             return [];
-        }
+    }
         let tree = bills.tree.selected.elf.tree;
         if(!tree){
             return [];
         }
         for(let node of tree.items){
-            if(node.children.length === 0 && node.data.optionChecked){//定额数据只能在最底层节点中
-                for(let perChecked of node.data.optionChecked){
-                    if(perChecked.type === itemType.ration){
-                        rst.push({itemQuery: {userID: userID, ID: perChecked.rationID}, rationType: rationType.ration});
+            for(let perChecked of node.data.optionChecked){
+                //选项直接是定额
+                if(perChecked.type === itemType.ration){
+                    rst.push({itemQuery: {userID: userID, ID: perChecked.rationID}, rationType: rationType.ration});
+                }
+                //选项下子选项是定额
+                else {
+                    let rationOpts = getOptions(perChecked, bills.tree.selected.elf.datas);
+                    for(let ration of rationOpts){
+                        if(ration.type === itemType.ration){
+                            rst.push({itemQuery: {userID: userID, ID: ration.rationID}, rationType: rationType.ration});
+                        }
                     }
                 }
             }

+ 12 - 9
web/building_saas/main/js/views/std_bills_lib.js

@@ -437,6 +437,7 @@ var billsLibObj = {
     jobsSetting: {
         "emptyRows":0,
         "headRows":1,
+        "rowHeaderWidth": 15,
         "headRowHeight":[25],
         "defaultRowHeight": 21,
         "cols":[{
@@ -461,6 +462,7 @@ var billsLibObj = {
     featuresSetting: {
         "emptyRows":0,
         "headRows":1,
+        "rowHeaderWidth": 15,
         "headRowHeight":[25],
         "defaultRowHeight": 21,
         "cols":[{
@@ -499,15 +501,16 @@ if($('#stdBillsSpread').height() === 0 || $('#qd').find('.bottom-content').heigh
 }
 
 $('#stdBillsTab').bind('click', function () {
-    refreshSubSpread();//subSpread、jobSpread、itemSpread显示问题
-    //$(".main-data-side-q").height($(window).height() - $(".header").height() - $(".toolsbar").height() -  $(".tools-bar-height-q").height() - 202);
-    var select = $('#stdBillsLibSelect');
-    billsLibObj.refreshBillsSpread();
-    billsLibObj.refreshBillsRelaSpread();
-    billsLibObj.checkBillsSpread();
-    if (select[0].options.length === 0) {
-        billsLibObj.loadStdBillsLib();
-    };
+    if(!projectReadOnly){
+        refreshSubSpread();//subSpread、jobSpread、itemSpread显示问题
+        var select = $('#stdBillsLibSelect');
+        billsLibObj.refreshBillsSpread();
+        billsLibObj.refreshBillsRelaSpread();
+        billsLibObj.checkBillsSpread();
+        if (select[0].options.length === 0) {
+            billsLibObj.loadStdBillsLib();
+        };
+    }
 });
 $('#stdBillsLibSelect').change(function () {
     $('#stdBillsSearchResult').hide();

+ 94 - 22
web/building_saas/main/js/views/std_ration_lib.js

@@ -9,6 +9,7 @@ var rationLibObj = {
     doAfterLoadGetRations: null, //获取章节树下定额后回调
     rationChapterSpread: null,
     sectionRationsSpread: null,
+    resultSpread: null,
     rationChapterTreeController: null,
     refreshSettingForHint: function () {
         TREE_SHEET_HELPER.initSetting($('#stdSectionRations')[0], rationLibObj.sectionRationsSetting);
@@ -35,6 +36,9 @@ var rationLibObj = {
         if (this.sectionRationsSpread) {
             this.sectionRationsSpread.refresh();
         }
+        if(this.resultSpread){
+            this.resultSpread.refresh();
+        }
     },
     loadStdRationLibs: function () {
         let select = $('#stdRationLibSelect');
@@ -121,14 +125,16 @@ var rationLibObj = {
         });
         args.sheet.repaint();
     },
-    setTagForHint: function (datas) {
-        let sheet = this.sectionRationsSpread.getActiveSheet();
+    setTagForHint: function (sheet, datas) {
         sheet.suspendPaint();
         sheet.suspendEvent();
         for(let i = 0, len = sheet.getRowCount(); i < len; i++){
             sheet.setTag(i, 0, '');
         }
         for(let i = 0, len = datas.length; i < len; i++){
+            if(datas[i].code === 'AA0032'){
+                console.log(datas[i]);
+            }
             sheet.setTag(i, 0, datas[i].hint ? datas[i].hint : '');
         }
         sheet.resumePaint();
@@ -143,7 +149,7 @@ var rationLibObj = {
             });
             SheetDataHelper.loadSheetHeader(setting, rationLibObj.sectionRationsSpread.getActiveSheet());
             SheetDataHelper.loadSheetData(setting, rationLibObj.sectionRationsSpread.getActiveSheet(), datas);
-            rationLibObj.setTagForHint(datas);
+            rationLibObj.setTagForHint(rationSheet, datas);
         };
         if (sectionID) {
             CommonAjax.post('/complementaryRation/api/getRationGljItemsBySection', {user_Id: userID, sectionId: sectionID}, function (datas) {
@@ -229,14 +235,14 @@ var rationLibObj = {
         let sectionNode = me.tree.items[row] || null;
         me.loadSectionRations(sectionNode && sectionNode.children.length === 0 ? sectionNode.data.ID : null);
     },
-    locateAtRation: function(code){
+    locateAtRation: function(libID, code){
         let me = rationLibObj;
         //查找定额,以确定定额所在章节节点
         let firstLibID = projectInfoObj.projectInfo.engineeringInfo.ration_lib.length > 0 ?
                         projectInfoObj.projectInfo.engineeringInfo.ration_lib[0].id : null;
         let locateRow = 0,
             locateSubRow = 0;
-        CommonAjax.post('/complementaryRation/api/getRationItem', {rationRepIds: [firstLibID], code: code}, function (ration) {
+        CommonAjax.post('/complementaryRation/api/getRationItem', {rationRepIds: [libID], code: code}, function (ration) {
             if(ration && ration.sectionId){
                 let sectionNode = me.tree.findNode(ration.sectionId);
                 if(sectionNode){
@@ -411,12 +417,14 @@ if($('#stdRationChapter').height() === 0 || $('#stdSectionRations').height() ===
 }
 
 $('#stdRationTab').bind('click', function () {
-    var select = $('#stdRationLibSelect');
-    rationLibObj.checkSpread();
-    if (select[0].options.length === 0) {
-        rationLibObj.loadStdRationLibs();
-        rationLibObj.loadStdRationContextMenu();
-    };
+    if(!projectReadOnly){
+        var select = $('#stdRationLibSelect');
+        rationLibObj.checkSpread();
+        if (select[0].options.length === 0) {
+            rationLibObj.loadStdRationLibs();
+            rationLibObj.loadStdRationContextMenu();
+        };
+    }
 });
 $('#stdRationLibSelect').change(function () {
     var select = $(this);
@@ -434,8 +442,28 @@ $('#rationSearchKeyword').bind('keypress', function (event) {
         $('#rationSearch').click();
     }
 });
+$('#rationSearchKeyword').keyup(function () {
+    let keyword = $('#rationSearchKeyword').val();
+    if(keyword === ''){
+        if($('#rationSearchResult').is(':visible')){
+            $('#rationSearchResult').hide();
+            $(".main-data-side-search", $('#rationSearchResult')).height(0);
+            autoFlashHeight();
+            rationLibObj.refreshSpread();
+        }
+    }
+});
 $('#rationSearch').click(function () {
     var keyword = $('#rationSearchKeyword').val(), rationLibID = $('#stdRationLibSelect').val();
+    if(keyword === ''){
+        if($('#rationSearchResult').is(':visible')){
+            $('#rationSearchResult').hide();
+            $(".main-data-side-search", $('#rationSearchResult')).height(0);
+            autoFlashHeight();
+            rationLibObj.refreshSpread();
+        }
+        return;
+    }
     var getResultHtml = function (result) {
         var html = [], i, serialNo;
         html.push('<div class="d-flex justify-content-between">');
@@ -449,13 +477,56 @@ $('#rationSearch').click(function () {
         html.push('</div>');
         return html.join('');
     };
+    let bindContextmenuOpr = function (sheet) {
+        $.contextMenu({
+            selector: '#rationSearchResult',
+            build: function($triggerElement, e){
+                //控制允许右键菜单在哪个位置出现
+                let offset = $('.main-data-side-search').offset(),
+                    x = e.pageX - offset.left,
+                    y = e.pageY - offset.top;
+                let target = sheet.hitTest(x, y);
+                if(target.hitTestType === 3 && typeof target.row !== 'undefined' && typeof target.col !== 'undefined'){//在表格内
+                    sheet.setActiveCell(target.row, target.col);
+                    return {
+                        callback: function(){},
+                        items: {
+                            "locate": {
+                                name: "定位至章节",
+                                disabled: function () {
+                                    return target.row >= rationLibObj.resultCache.length;
+                                },
+                                icon: "fa-arrow-left",
+                                callback: function (key, opt) {
+                                    let data = rationLibObj.resultCache[target.row];
+                                    $('#rationSearchResult').hide();
+                                    $(".main-data-side-search", $('#rationSearchResult')).height(0);
+                                    autoFlashHeight();
+                                    rationLibObj.refreshSpread();
+                                    rationLibObj.locateAtRation(data.rationRepId, data.code);
+                                }}
+                        }
+                    };
+                }
+                else{
+                    return false;
+                }
+            }
+        });
+    };
     var showResult = function (result) {
-        var resultSpread = SheetDataHelper.createNewSpread($('.main-data-side-search')[0]);
-
-        SheetDataHelper.loadSheetHeader(rationLibObj.sectionRationsSetting, resultSpread.getActiveSheet());
-        SheetDataHelper.loadSheetData(rationLibObj.sectionRationsSetting, resultSpread.getActiveSheet(), result);
-
-        resultSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, rationLibObj.onRationSpreadCellDoubleClick);
+        rationLibObj.resultCache = result;
+        if(!rationLibObj.resultSpread){
+            let resultSpread = SheetDataHelper.createNewSpread($('.main-data-side-search')[0]);
+            rationLibObj.resultSpread = resultSpread;
+            bindContextmenuOpr(resultSpread.getActiveSheet());
+            SheetDataHelper.loadSheetHeader(rationLibObj.sectionRationsSetting, resultSpread.getActiveSheet());
+            resultSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, rationLibObj.onRationSpreadCellDoubleClick);
+        }else {
+            rationLibObj.resultSpread.refresh();
+        }
+        SheetDataHelper.loadSheetData(rationLibObj.sectionRationsSetting, rationLibObj.resultSpread.getActiveSheet(), result);
+        rationLibObj.setTagForHint(rationLibObj.resultSpread.getActiveSheet(), result);
     };
     CommonAjax.post('/complementaryRation/api/findRation', {'user_id': userID, 'rationRepId': rationLibID, 'keyword': keyword}, function (result) {
         //sort
@@ -465,14 +536,15 @@ $('#rationSearch').click(function () {
             else if(a.code < b.code) rst = -1;
             return rst;
         });
-        var resultObj = $('#rationSearchResult'), resultSpread = null;
-        resultObj.empty();
-        resultObj.append(getResultHtml(result));
-        $('a', resultObj).click(function () {
+        var resultObj = $('#rationSearchResult');
+        /*resultObj.empty();
+        resultObj.append(getResultHtml(result));*/
+        $('#rationSearchCount').text(`搜索结果:${result.length.toString()}`);
+        $('a', result).unbind('click');
+        $('a', resultObj).bind('click', function () {
             resultObj.hide();
             $(".main-data-side-search", resultObj).height(0);
             autoFlashHeight();
-            //$(".main-data-side-d").height($(window).height() - $(".header").height() - $(".toolsbar").height() -  $(".tools-bar-height-d").height() - 202);
             rationLibObj.refreshSpread();
         });
         resultObj.show();

+ 54 - 68
web/building_saas/main/js/views/zmhs_view.js

@@ -116,12 +116,15 @@ let zmhs_obj = {
         let me = zmhs_obj;
         if(me.coeSheetData[context.row]){
             let data = me.coeSheetData[context.row];
-            $('#coe_ration').val(data.coes[0].amount);
+            for(let c of data.coes){
+                $("#"+ c.coeType).val(c.amount);
+            }
+            /*$('#coe_ration').val(data.coes[0].amount);
             $('#manual').val(data.coes[1].amount);
             $('#material').val(data.coes[2].amount);
             $('#manchine').val(data.coes[3].amount);
             $('#mainM').val(data.coes[4].amount);
-            $('#equipment').val(data.coes[5].amount);
+            $('#equipment').val(data.coes[5].amount);*/
         }
     },
     updateCusCoeAfterEditor:function(){
@@ -135,70 +138,53 @@ let zmhs_obj = {
         var coe = _.find(zmhs_obj.coeSheetData, function (c) {
             return c.coeID == -1;
         });
-        var newValue = zmhs_obj.numberValueChecking($('#' + id).val());
-        if (newValue) {
-            newValue = _.round(newValue, 2);
-            if (newValue == coe.coes[name].amount) return;
-            if (id == 'coe_ration') {
-                $('#coe_ration').val(newValue);
-                $('#manual').val(newValue);
-                $('#material').val(newValue);
-                $('#manchine').val(newValue);
-                $('#mainM').val(newValue);
-                $('#equipment').val(newValue);
+        if(coe){
+            let newValue = zmhs_obj.numberValueChecking($('#' + id).val());
+            if (newValue) {
+                newValue = _.round(newValue, 2);
+                if (newValue == coe.coes[name].amount) return;
+                if (id == '定额') {
+                    for(let c of coe.coes){
+                        $('#'+c.coeType).val(newValue)
+                    }
+                    /*$('#coe_ration').val(newValue);
+                    $('#manual').val(newValue);
+                    $('#material').val(newValue);
+                    $('#manchine').val(newValue);
+                    $('#mainM').val(newValue);
+                    $('#equipment').val(newValue);*/
+                } else {
+                    $('#' + id).val(newValue);
+                }
             } else {
-                $('#' + id).val(newValue);
+                $('#' + id).val(coe.coes[name].amount);
             }
-        } else {
-            $('#' + id).val(coe.coes[name].amount);
         }
+
     },
     checkIfNeedUpdate(){
-        var data = _.find(zmhs_obj.coeSheetData, function (c) {
+        let data = _.find(zmhs_obj.coeSheetData, function (c) {
             return c.coeID == -1;
         });
-        var result = {
-            isNeed: false
-        }
-        var coe_ration = $('#coe_ration').val();
-        var manual = $('#manual').val();
-        var material = $('#material').val();
-        var manchine = $('#manchine').val();
-        var mainM = $('#mainM').val();
-        var equipment = $('#equipment').val();
-        if (coe_ration != data.coes[0].amount) {
-            result.isNeed = true;
-            data.coes[0].amount = coe_ration;
-        }
-        if (manual != data.coes[1].amount) {
-            result.isNeed = true;
-            data.coes[1].amount = manual;
-        }
-        if (material != data.coes[2].amount) {
-            result.isNeed = true;
-            data.coes[2].amount = material;
-        }
-        if (manchine != data.coes[3].amount) {
-            result.isNeed = true;
-            data.coes[3].amount = manchine;
-        }
-        if (mainM != data.coes[4].amount) {
-            result.isNeed = true;
-            data.coes[4].amount = mainM;
-        }
-        if (equipment != data.coes[5].amount) {
-            result.isNeed = true;
-            data.coes[5].amount = equipment;
-        }
-        if (result.isNeed) {
-            result.doc = {
-                coes: data.coes
-            };
-            result.query = {
-                projectID: data.projectID,
-                ID: data.ID,
-                rationID: data.rationID
-            };
+        let result = {isNeed: false};
+        if(data){
+            for(let c of data.coes){
+                let amount = $("#"+c.coeType).val();
+                if(amount!=c.amount){
+                    result.isNeed = true;
+                    c.amount = amount;
+                }
+            }
+            if (result.isNeed) {
+                result.doc = {
+                    coes: data.coes
+                };
+                result.query = {
+                    projectID: data.projectID,
+                    ID: data.ID,
+                    rationID: data.rationID
+                };
+            }
         }
         return result;
 
@@ -229,22 +215,22 @@ let zmhs_obj = {
         let recode = me.coeSheetData[args.row];
         projectObj.project.ration_coe.adjustCoeClick(recode, newval);
     },
-    generateHtmlString: function (context,cellRect) {
+    generateHtmlString: function (context,cellRect) {//这里要改成动态的了,根据自定义系数内容生成对应的输入框
         let me = zmhs_obj;
         let height = cellRect.height;
         let newString = "<div style='height:"+ height+"px'><div onclick='zmhs_obj.coeSheet.endEdit()' style='margin:-1px 1px 0px'>自定义系数</div></div><form style='margin-top:1px' ><table  width='100%'  cellpadding='0'  border='1px' bordercolor='#CCCCCC' cellspacing='0px' style='border-collapse:collapse;font-size: 10px;'>";
-        newString += me.getOneRow('定额', 0, 'coe_ration',height);
-        newString += me.getOneRow('人工', 1, 'manual',height);
-        newString += me.getOneRow('材料', 2, 'material',height);
-        newString += me.getOneRow('机械', 3, 'manchine',height);
-        newString += me.getOneRow('主材', 4, 'mainM',height);
-        newString += me.getOneRow('设备', 5, 'equipment',height);
+        let cus_coe =  me.coeSheetData[context.row];
+        if(cus_coe){
+            for(let i =0;i< cus_coe.coes.length;i++){
+                newString += me.getOneRow(cus_coe.coes[i].coeType, i, cus_coe.coes[i].coeType,height)
+            }
+        }
         newString += "</table></form>";
         return newString;
     },
     getOneRow: function (text, name, id,inputHeight) {
-        var rowstr = "<tr ><td style='width: 40%'>" + text
-            + ":</td><td style='width: 60%' align='right'><input type='text' value='1' name=" + name
+        var rowstr = "<tr ><td style='width: 50%'>" + text
+            + ":</td><td style='width: 50%' align='right'><input type='text' value='1' name=" + name
             + " style='width:40px;border:0;height:"+ inputHeight+"px;' align='right' id=" + id + " onchange='zmhs_obj.onInputChange(this.id,this.name)' autocomplete='off'></td></tr>";
         return rowstr;
 

+ 133 - 5
web/building_saas/pm/html/project-management.html

@@ -250,7 +250,7 @@
     </div>
 </div>
 <!--弹出新建单位工程-->
-<div class="modal fade" id="add-tender-dialog" data-backdrop="static">
+<!--<div class="modal fade" id="add-tender-dialog" data-backdrop="static">
     <div class="modal-dialog" role="document">
         <div class="modal-content">
             <div class="modal-header">
@@ -310,10 +310,10 @@
                                 <input name="valuation_type" checked id="radioBill" value="bill" type="radio" class="custom-control-input">
                                 <label class="custom-control-label" for="radioBill">清单计价</label>
                             </label>
-                          <!--  <label class="custom-control custom-radio" style="margin-left: 5px;">
+                          &lt;!&ndash;  <label class="custom-control custom-radio" style="margin-left: 5px;">
                                 <input name="valuation_type" id="radioRation" value="ration" type="radio" class="custom-control-input">
                                 <label class="custom-control-label" for="radioRation">定额计价</label>
-                            </label>-->
+                            </label>&ndash;&gt;
                         </div>
                     </div>
                     <div style="margin-top: 15px;" class="input-group">
@@ -334,8 +334,8 @@
                     <div style="margin-top: 15px;" class="input-group" id="taxType_div">
                         <label style="margin-top: 8px;">计税方式</label>
                         <select style="margin-left: 5px; border-radius: .25rem;" class="form-control" id="taxType">
-                            <!--<option value="1">一般计税</option>
-                            <option value="2">简易计税</option>-->
+                            &lt;!&ndash;<option value="1">一般计税</option>
+                            <option value="2">简易计税</option>&ndash;&gt;
                         </select>
                     </div>
                     <div style="margin-top: 15px;" class="input-group">
@@ -352,6 +352,134 @@
             </div>
         </div>
     </div>
+</div>-->
+<div class="modal fade" id="add-tender-dialog" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">新建 <i class="fa fa-sticky-note-o"></i> 单位工程</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <form>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">建设项目</label>
+                        <div class="col">
+                            <div class="input-group input-group-sm">
+                                <input type="text" class="form-control" aria-label="Text input with dropdown button" id="poj-name" autocomplete="off">
+                                <div class="input-group-append">
+                                    <button class="btn btn-outline-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
+                                    <div class="dropdown-menu dropdown-menu-right w-100" id="poj-name-list">
+                                        <a class="dropdown-item" href="#">Action</a>
+                                        <a class="dropdown-item" href="#">Another action</a>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <span class="form-text text-info" id="poj-name-info" style="display: none;">新建 “汽车生产车间5”</span>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">单项工程</label>
+                        <div class="col">
+                            <div class="input-group input-group-sm">
+                                <input type="text" class="form-control" aria-label="Text input with dropdown button" id="eng-name" autocomplete="off">
+                                <div class="input-group-append">
+                                    <button class="btn btn-outline-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></button>
+                                    <div class="dropdown-menu dropdown-menu-right w-100" id="eng-name-list">
+                                        <a class="dropdown-item" href="#">Action</a>
+                                        <a class="dropdown-item" href="#">Another action</a>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                    <span class="form-text text-info" id="eng-name-info" style="display: none;">新建 “左2号生产车间2”</span>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">单位工程</label>
+                        <div class="col">
+                            <input type="text" class="form-control form-control-sm" placeholder="输入单位工程名称" id="tender-name" autocomplete="off">
+                        </div>
+                    </div>
+                    <span class="form-text text-danger" id="tender-name-info" style="display: none;">已存在 “建筑工程1”</span>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">单价文件</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="unit-price">
+                                <option value="">新建单价文件</option>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">费率文件</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="tender-fee-rate">
+                                <option value="">新建费率文件</option>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价方式</label>
+                        <div class="col">
+                            <div class="custom-control custom-radio custom-control-inline">
+                                <input type="radio" value="bill" checked id="radioBill" name="valuation_type" class="custom-control-input">
+                                <label class="custom-control-label" for="radioBill">清单计价</label>
+                            </div>
+                           <!-- <div class="custom-control custom-radio custom-control-inline">
+                                <input type="radio" value="ration" id="radioRation" name="valuation_type" class="custom-control-input">
+                                <label class="custom-control-label" for="radioRation">定额计价</label>
+                            </div>-->
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价规则</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="valuation">
+                            </select>
+                        </div>
+                    </div>
+                    <span class="form-text text-danger" id="valuation-info" style="display: none;">请选择计价规则</span>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">工程专业</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="tender-engineering">
+                            </select>
+                        </div>
+                    </div>
+                    <span class="form-text text-danger" id="engineering-info" style="display: none;">请选择工程专业</span>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">费用标准</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="tender-feeStandard"></select>
+                        </div>
+                    </div>
+                    <span class="form-text text-danger" id="feeStandard-info" style="display: none;">请选择费用标准</span>
+                    <div class="form-group row" id="taxType_div">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计税方式</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="taxType">
+                                &lt;!&ndash;<option value="1">一般计税</option>
+                                <option value="2">简易计税</option>&ndash;&gt;
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计算程序</label>
+                        <div class="col">
+                            <select class="form-control  form-control-sm" id="tender-calcProgram">
+                            </select>
+                        </div>
+                    </div>
+                    <span class="form-text text-danger" id="calcProgram-info" style="display: none;">请选择计算程序</span>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <a href="javascript:void(0);" class="btn btn-primary" id="add-tender-confirm">确定</a>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
 </div>
 <!--弹出新建文件夹-->
 <div class="modal fade" id="add-folder-dialog" data-backdrop="static">

+ 30 - 6
web/building_saas/pm/js/pm_newMain.js

@@ -1247,7 +1247,7 @@ $(document).ready(function() {
                 }
                 return null;
             }
-            let matchOpt = getProjOpt($('#poj-name-list').find('button'));
+            let matchOpt = getProjOpt($('#poj-name-list').find('a'));
             if(matchOpt){
                 matchOpt.click();
             }
@@ -1530,7 +1530,7 @@ $(document).ready(function() {
                 $("#tender-fee-rate").children("option").first().val("newFeeRate-"+engLib.fee_lib[0].id);
             }*/
            //2018-08-29  费率改为和计税方式绑定在一起 所以在这里还不能确定标准费率库ID
-            $("#tender-fee-rate").children("option").first().val("newFeeRate-");
+            $("#tender-fee-rate").children("option").first().val("newFeeRate@@");
             $("#tender-engineering").parent().siblings('.hidden-area').slideDown('fast');
         }
         else {
@@ -2164,7 +2164,16 @@ function setProjOptions(projs, selected){
         setFileOptions(firstProj.data.ID);
         setEngOptions(firstProj.data.ID);
         for(let i = 0, len = projs.length; i < len; i++){
-            let proj = $("<button>").val(projs[i].data.ID).text(projs[i].data.name);
+            let $proj = $("<a>").val(projs[i].data.ID).text(projs[i].data.name);
+            $proj.addClass("dropdown-item");
+            $proj.attr("href", "javascript:void(0);");
+            $proj.click(function () {
+                $("#poj-name").val(projs[i].data.name);
+                setFileOptions(projs[i].data.ID);
+                setEngOptions(projs[i].data.ID);
+                $('#poj-name-info').hide();
+            });
+            /*let proj = $("<button>").val(projs[i].data.ID).text(projs[i].data.name);
             proj.addClass("dropdown-item");
             proj.attr("type", "button");
             proj.click(function () {
@@ -2172,8 +2181,8 @@ function setProjOptions(projs, selected){
                 setFileOptions(projs[i].data.ID);
                 setEngOptions(projs[i].data.ID);
                 $('#poj-name-info').hide();
-            });
-            $("#poj-name-list").append(proj);
+            });*/
+            $("#poj-name-list").append($proj);
         }
     }
     else {
@@ -2209,6 +2218,21 @@ function setEngOptions(projID){
         if(engineerings.length > 0){
             $("#eng-name").val(engineerings[0].data.name);
             for(let i = 0, len = engineerings.length; i < len; i++){
+                //let eng = $("<button>").val(engineerings[i].data.ID).text(engineerings[i].data.name);
+                let $eng = $('<a>').val(engineerings[i].data.ID).text(engineerings[i].data.name);
+                $eng.prop('href', 'javascript:void(0);');
+                $eng.addClass("dropdown-item");
+                //eng.attr("type", "button");
+                $eng.click(function () {
+                    $("#eng-name").val(engineerings[i].data.name);
+                    $('#eng-name-info').hide();
+                });
+                $("#eng-name-list").append($eng);
+            }
+        }
+        /*if(engineerings.length > 0){
+            $("#eng-name").val(engineerings[0].data.name);
+            for(let i = 0, len = engineerings.length; i < len; i++){
                 let eng = $("<button>").val(engineerings[i].data.ID).text(engineerings[i].data.name);
                 eng.addClass("dropdown-item");
                 eng.attr("type", "button");
@@ -2218,7 +2242,7 @@ function setEngOptions(projID){
                 });
                 $("#eng-name-list").append(eng);
             }
-        }
+        }*/
     }
 }
 

+ 6 - 2
web/common/html/header.html

@@ -1,5 +1,9 @@
 <nav class="navbar navbar-expand-lg p-0 d-flex">
-    <a style="text-decoration: none" href="/pm" class="header-logo">
+    <% if(controller === 'boot'){ %>
+    <a style="text-decoration: none" href="javascript:void(0);" class="header-logo">
+    <% }else { %>
+        <a style="text-decoration: none" href="/pm" class="header-logo">
+    <% } %>
         <div class="v-title">纵横云计价</div>
         <div class="p-title"><%= versionName %></div>
     </a>
@@ -27,7 +31,7 @@
                 <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown"><%= sessionUser.real_name === '' ? sessionUser.mobile : sessionUser.real_name %></a>
                 <div class="dropdown-menu dropdown-menu-right">
                     <a class="dropdown-item" href="/user/info" target="_blank">账号资料</a>
-                    <a class="dropdown-item" href="user-buy.html" target="_blank">产品购买</a>
+                    <a class="dropdown-item" href="/user/buy" target="_blank">产品激活</a>
                     <a class="dropdown-item" href="/user/preferences" target="_blank">登录设置</a>
                     <div class="dropdown-divider"></div>
                     <a class="dropdown-item" href="/logout">退出登录</a>

+ 55 - 29
web/over_write/js/chongqing_2018.js

@@ -46,13 +46,18 @@ if(typeof materialComponent !== 'undefined'){
 }
 
 // CSL, 2018-08-21 计算程序、基数 的覆盖。---------------------------------------------------------------------------------
-baseMaterialTypes.push(gljType.OTHER_MATERIAL);
-allMaterialTypes.delete(gljType.EQUIPMENT);
-baseMachineTypes.delete(gljType.MACHINE_COMPOSITION);
-baseMachineTypes.push(gljType.INSTRUMENT, gljType.FUEL_POWER_FEE, gljType.DEPRECIATION_FEE,
-    gljType.INSPECTION_FEE, gljType.MAINTENANCE, gljType.DISMANTLING_FREIGHT_FEE,
-    gljType.VERIFICATION_FEE, gljType.OTHER_FEE, gljType.OTHER_MACHINE_USED);
-baseMachineMasterTypes.push(gljType.INSTRUMENT);
+let isCQ2018 = true;
+
+if(typeof baseMaterialTypes !== 'undefined'){
+    baseMaterialTypes.push(gljType.OTHER_MATERIAL);
+    allMaterialTypes.delete(gljType.EQUIPMENT);
+    baseMachineTypes.delete(gljType.MACHINE_COMPOSITION);
+    baseMachineTypes.push(gljType.INSTRUMENT, gljType.FUEL_POWER_FEE, gljType.DEPRECIATION_FEE,
+        gljType.INSPECTION_FEE, gljType.MAINTENANCE, gljType.DISMANTLING_FREIGHT_FEE,
+        gljType.VERIFICATION_FEE, gljType.OTHER_FEE, gljType.OTHER_MACHINE_USED);
+    baseMachineMasterTypes.push(gljType.INSTRUMENT);
+}
+
 
 function overwriteRationCalcBases (taxType){
     if (rationCalcBases){
@@ -71,7 +76,7 @@ function overwriteRationCalcBases (taxType){
             return calcTools.rationBaseFee(node, [gljType.OTHER_MATERIAL], priceTypes.ptBasePrice, isTender);
         };
         rationCalcBases['定额施工机具使用费'] = function (node, isTender) {
-            return calcTools.rationBaseFee(node, [gljType.GENERAL_MACHINE, gljType.INSTRUMENT], priceTypes.ptBasePrice, isTender);
+            return calcTools.rationBaseFee(node, [gljType.GENERAL_MACHINE, gljType.INSTRUMENT, gljType.OTHER_MACHINE_USED], priceTypes.ptBasePrice, isTender);
         };
         rationCalcBases['市场价主材费'] = function (node, isTender) {
             return calcTools.rationBaseFee(node, [gljType.MAIN_MATERIAL], priceTypes.ptMarketPrice, isTender);
@@ -85,7 +90,7 @@ function overwriteRationCalcBases (taxType){
         rationCalcBases['材料费价差'] = function (node, isTender) {
             return calcTools.rationBaseFee(node, baseMaterialTypes, priceTypes.ptDiffPrice, isTender);
         };
-        if (isJY){
+/*        if (isJY){
             rationCalcBases['计价材料价差'] = function (node, isTender) {
                 let baseMaterialTypesWithoutOtherMaterial = [
                     gljType.GENERAL_MATERIAL,
@@ -97,7 +102,7 @@ function overwriteRationCalcBases (taxType){
                 ];
                 return calcTools.rationBaseFee(node, baseMaterialTypesWithoutOtherMaterial, priceTypes.ptDiffPrice, isTender);
             };
-        };
+        };*/
         rationCalcBases['机上人工费价差'] = function (node, isTender) {
             return calcTools.rationBaseFee(node, [gljType.MACHINE_LABOUR], priceTypes.ptDiffPrice, isTender);
         };
@@ -109,33 +114,26 @@ function overwriteRationCalcBases (taxType){
                 return calcTools.rationBaseFee(node, [gljType.OTHER_MACHINE_USED], priceTypes.ptBasePrice, isTender);
             };
             rationCalcBases['机械折旧费'] = function (node, isTender) {
-                return calcTools.machineDetailFee(node, node.data.gljList, [], baseMachineMasterTypes,
-                    gljType.DEPRECIATION_FEE, isTender);
+                return calcTools.machineDetailFee(node, node.data.gljList, [], gljType.DEPRECIATION_FEE, isTender);
             };
             rationCalcBases['特大机械检修费'] = function (node, isTender) {
-                return calcTools.machineDetailFee(node, node.data.gljList, [1, 2], baseMachineMasterTypes,
-                    gljType.INSPECTION_FEE, isTender);
+                return calcTools.machineDetailFee(node, node.data.gljList, [1, 2], gljType.INSPECTION_FEE, isTender);
             };
             rationCalcBases['中小机械检修费'] = function (node, isTender) {
-                return calcTools.machineDetailFee(node, node.data.gljList, [3, 4], baseMachineMasterTypes,
-                    gljType.INSPECTION_FEE, isTender);
+                return calcTools.machineDetailFee(node, node.data.gljList, [3, 4], gljType.INSPECTION_FEE, isTender);
             };
             rationCalcBases['特大机械维护费'] = function (node, isTender) {
-                return calcTools.machineDetailFee(node, node.data.gljList, [1, 2], baseMachineMasterTypes,
-                    gljType.MAINTENANCE, isTender);
+                return calcTools.machineDetailFee(node, node.data.gljList, [1, 2], gljType.MAINTENANCE, isTender);
             };
             rationCalcBases['中小机械维护费'] = function (node, isTender) {
-                return calcTools.machineDetailFee(node, node.data.gljList, [3, 4], baseMachineMasterTypes,
-                    gljType.MAINTENANCE, isTender);
+                return calcTools.machineDetailFee(node, node.data.gljList, [3, 4], gljType.MAINTENANCE, isTender);
             };
             rationCalcBases['安拆费及场外运输费'] = function (node, isTender) {
-                return calcTools.machineDetailFee(node, node.data.gljList, [], baseMachineMasterTypes,
-                    gljType.DISMANTLING_FREIGHT_FEE, isTender);
-            };
-            rationCalcBases['燃料动力费'] = function (node, isTender) {
-                return calcTools.machineDetailFee(node, node.data.gljList, [], baseMachineMasterTypes,
-                    gljType.FUEL_POWER_FEE, isTender);
+                return calcTools.machineDetailFee(node, node.data.gljList, [], gljType.DISMANTLING_FREIGHT_FEE, isTender);
             };
+/*            rationCalcBases['燃料动力费'] = function (node, isTender) {
+                return calcTools.machineDetailFee(node, node.data.gljList, [], gljType.FUEL_POWER_FEE, isTender);
+            };*/
             rationCalcBases['定额仪器仪表费'] = function (node, isTender) {
                 return calcTools.rationBaseFee(node, [gljType.INSTRUMENT], priceTypes.ptBasePrice, isTender);
             };
@@ -204,8 +202,12 @@ var cpFeeTypes2018 = [
     {type: 'environmentTax', name: '环境保护税'},
     {type: 'common', name: '工程造价'}
 ];
-cpFeeTypes.splice(0, cpFeeTypes.length);
-for (let e of cpFeeTypes2018) cpFeeTypes.push(e);
+
+if(typeof cpFeeTypes !== 'undefined'){
+    cpFeeTypes.splice(0, cpFeeTypes.length);
+    for (let e of cpFeeTypes2018) cpFeeTypes.push(e);
+}
+
 
 
 //清单计算基数相关
@@ -284,8 +286,32 @@ if(typeof figureClassTemplate !== 'undefined'){
     figureClassTemplate['ADDED_VALUE_TAX'] = {flag: fixedFlag.ADDED_VALUE_TAX, filter: ['SJ', 'ZZS', 'SQGCZJ']}
 };
 //去除分类分包费
-if($('#cbClassList')){
+if(typeof $ !== 'undefined' && $('#cbClassList')){
     $('#cbClassList').find('li:eq(5)').remove();
 }
 
 
+
+
+//这个文档浏览器库和服务器端共用,所以这个文件中用到的变量都要记得做undefined判断,不然后端读取时会有问题
+//=================================================== 前后端分割线 ======================================================================
+if(typeof module !== 'undefined'){
+    module.exports = {
+        getCusCoeContent: getCusCoeContent,
+        getCustomerCoeData: getCustomerCoeData
+    };
+}
+
+function getCusCoeContent() {
+    return '人工×1,材料×1,施工机具×1,主材×1'
+}
+
+function getCustomerCoeData() {
+    return [
+        {amount:1, operator:'*', gljCode:null, coeType:'定额'},
+        { amount:1, operator:'*', gljCode:null, coeType:'人工'},
+        { amount:1, operator:'*', gljCode:null, coeType:'材料'},
+        { amount:1, operator:'*', gljCode:null, coeType:'施工机具'},
+        { amount:1, operator:'*', gljCode:null, coeType:'主材'}
+    ]
+}

+ 302 - 0
web/users/html/user-buy.html

@@ -0,0 +1,302 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<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/bootstrap/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/web/building_saas/css/main.css">
+    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
+</head>
+
+<body>
+  <div class="header">
+      <%include ../../common/html/header.html %>
+  </div>
+    <div class="main">
+        <div class="poj-manage container-fluid">
+            <div class="row">
+                <div class="col-lg-2">
+                    <div class="mt-3">
+                        <ul class="nav nav-pills flex-column">
+                            <li class="nav-item">
+                                <a class="nav-link" href="/user/info">账号资料</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link" href="/user/safe">账号安全</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link active" href="/user/buy">产品激活</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link" href="/user/preferences">登录设置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="col-lg-10 side-content">
+                    <div class="col-lg-12 my-3">
+                        <!-- <legend>购买企业版</legend>
+                        <div class="card card-body mb-5">
+                            <h3 class="card-title">Smartcost 企业版</h3>
+                            <p class="card-text">简介</p>
+                            <a class="btn btn-primary" href="#">了解企业版</a>
+                        </div> -->
+                        <legend class=" mb-4">激活专业版</legend>
+                        <div class="row">
+                            <div class="col-sm-4 mb-5">
+                                <div class="card">
+                                  <div class=" card-body">
+                                    <h3 class="card-title">免费版 </h3>
+                                      <p class="card-text">
+                                      <ul class="pl-3">
+                                          <li>只可创建 50 个单位工程</li>
+                                          <li>报表带水印</li>
+                                      </ul>
+                                      </p>
+                                  </div>
+                                    <ul class="list-group list-group-flush">
+                                        <% if (compilationList.length > 0) {%>
+                                        <% compilationList.forEach(function(compilation) { %>
+                                        <% if (compilation.is_release === true) { %>
+                                        <li class="list-group-item d-flex justify-content-between">
+                                            <%= compilation.name %>
+                                            <a class="btn disabled btn-sm"><i class="fa fa-check"></i> 已激活</a>
+                                        </li>
+                                        <% } %>
+                                        <% }) %>
+                                        <% } %>
+                                    </ul>
+                                </div>
+                            </div>
+                            <div class="col-sm-4 mb-5">
+                                <div class="card">
+                                  <div class=" card-body">
+                                    <h3 class="card-title">专业版</h3>
+                                      <p class="card-text">
+                                      <ul class="pl-3">
+                                          <li>创建单位工程无限制</li>
+                                          <li>报表无水印</li>
+                                      </ul>
+                                      </p>
+                                  </div>
+                                    <ul class="list-group list-group-flush">
+                                        <% if (compilationList.length > 0) {%>
+                                        <% compilationList.forEach(function(compilation) { %>
+                                        <li class="list-group-item d-flex justify-content-between">
+                                            <%= compilation.name %>
+                                            <% if (compilation.isUpgrade === undefined || compilation.isUpgrade !== true) { %>
+                                            <a class="btn btn-primary btn-sm" href="activ" data-toggle="modal" data-target="#activ">立即激活</a>
+                                            <% } else { %>
+                                            <a class="btn btn-outline-secondary btn-sm" href="activ2" data-toggle="modal" data-target="#activ2"><i class="fa fa-check"></i> 已激活</a>
+                                            <% } %>
+                                        </li>
+                                        <% }) %>
+                                        <% } %>
+                                        <!--<li class="list-group-item d-flex justify-content-between">-->
+                                        <!--重庆(2015)-->
+                                        <!--<a class="btn btn-outline-secondary btn-sm" href="activ2" data-toggle="modal" data-target="#activ2"><i class="fa fa-check"></i> 已激活</a>-->
+                                        <!--</li>-->
+                                    </ul>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!--激活产品-->
+    <div class="modal fade" id="activ" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <div class="modal-dialog modal-lg" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                  <h5 class="modal-title">联系销售代表激活</h5>
+                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                  </button>
+                </div>
+                <div class="modal-body">
+                  <div class="row px-3">
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">刘飞</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">广东办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">姜栋</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">广东办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">冯娟</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">广东办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">何耀</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">广东办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">杨克松</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">广东办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">黄俊杰</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">广东办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div class="modal-footer">
+                  <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!--售后服务-->
+    <div class="modal fade" id="activ2" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <div class="modal-dialog modal-lg" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                  <h5 class="modal-title">重庆(2015)售后服务</h5>
+                  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">×</span>
+                  </button>
+                </div>
+                <div class="modal-body">
+                  <div class="row px-3">
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">王星植</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">重庆办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">张文远</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">重庆办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">李清学</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">重庆办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">周洪波</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">重庆办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                    <div class="col-4 mb-4">
+                      <div class="card">
+                        <div class="card-body">
+                          <h4 class="card-title">邹芝达</h4>
+                          <h6 class="card-subtitle mb-2 text-muted">重庆办</h6>
+                        </div>
+                        <ul class="list-group list-group-flush">
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="腾讯QQ"><i class="fa fa-qq"></i> 914630468</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="手机号码"><i class="fa fa-tablet"></i> 15812644017</li>
+                          <li class="list-group-item" data-toggle="tooltip" data-placement="bottom" title="" data-original-title="固定电话"><i class="fa fa-phone"></i> 0756-3850891</li>
+                        </ul>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div class="modal-footer">
+                  <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!-- JS. -->
+  <script src="/web/building_saas/js/global.js"></script>
+  <script src="/web/users/js/user.js"></script>
+</body>
+<script type="text/javascript">
+    autoFlashHeight();
+</script>
+
+</html>

+ 1 - 1
web/users/html/user-info.html

@@ -28,7 +28,7 @@
                             <a class="nav-link" href="/user/safe">账号安全</a>
                         </li>
                         <li class="nav-item">
-                            <a class="nav-link" href="/user/buy">产品购买</a>
+                            <a class="nav-link" href="/user/buy">产品激活</a>
                         </li>
                         <li class="nav-item">
                             <a class="nav-link" href="/user/preferences">登录设置</a>

+ 1 - 1
web/users/html/user-safe.html

@@ -31,7 +31,7 @@
                             <a class="nav-link active" href="/user/safe">账号安全</a>
                         </li>
                         <li class="nav-item">
-                            <a class="nav-link" href="/user/buy">产品购买</a>
+                            <a class="nav-link" href="/user/buy">产品激活</a>
                         </li>
                         <li class="nav-item">
                             <a class="nav-link" href="/user/preferences">登录设置</a>

+ 1 - 1
web/users/html/user-set.html

@@ -29,7 +29,7 @@
                                 <a class="nav-link" href="/user/safe">账号安全</a>
                             </li>
                             <li class="nav-item">
-                                <a class="nav-link" href="/user/buy">产品购买</a>
+                                <a class="nav-link" href="/user/buy">产品激活</a>
                             </li>
                             <li class="nav-item">
                                 <a class="nav-link active" href="/user/preferences">登录设置</a>

+ 1 - 1
web/users/js/user.js

@@ -58,7 +58,7 @@ function showError(msg, element) {
     if (element !== null) {
         element.parent().addClass('has-danger');
     }
-    let html = '<div class="form-control-feedback">' + msg + '</div>';
+    let html = '<div class="form-control-feedback" style="color: red">' + msg + '</div>';
     if (element.siblings('.form-control-feedback').length > 0) {
         element.siblings('.form-control-feedback').text(msg);
     } else {