Kaynağa Gözat

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

TonyKang 4 yıl önce
ebeveyn
işleme
7f84740e6b
45 değiştirilmiş dosya ile 4047 ekleme ve 2828 silme
  1. 18 0
      config/config.js
  2. 2 1
      logs/online_logs.js
  3. 1 6
      modules/glj/models/unit_price_model.js
  4. 1 1
      modules/main/controllers/ration_controller.js
  5. 52 9
      modules/main/facade/ration_facade.js
  6. 17 0
      modules/pm/controllers/pm_controller.js
  7. 29 1
      modules/pm/facade/pm_facade.js
  8. 1 1
      modules/pm/models/project_model.js
  9. 2 2
      modules/users/controllers/cld_controller.js
  10. 37 18
      public/web/gljUtil.js
  11. 34 9
      public/web/scMathUtil.js
  12. 35 0
      public/web/sheet/sheet_data_helper.js
  13. 11 5
      public/web/syntax-detection.js
  14. 9 0
      web/building_saas/css/main.css
  15. BIN
      web/building_saas/img/vip3.png
  16. 12 0
      web/building_saas/js/global.js
  17. 4 2
      web/building_saas/main/html/main.html
  18. 1 1
      web/building_saas/main/js/controllers/block_controller.js
  19. 6 1
      web/building_saas/main/js/main.js
  20. 22 3
      web/building_saas/main/js/models/calc_base.js
  21. 3240 2506
      web/building_saas/main/js/models/calc_program.js
  22. 95 95
      web/building_saas/main/js/models/feeRateConsts.js
  23. 5 0
      web/building_saas/main/js/models/project_glj.js
  24. 1 1
      web/building_saas/main/js/models/ration_glj.js
  25. 9 9
      web/building_saas/main/js/views/glj_col.js
  26. 12 5
      web/building_saas/main/js/views/glj_view.js
  27. 8 8
      web/building_saas/main/js/views/main_tree_col.js
  28. 56 4
      web/building_saas/main/js/views/project_property_projFeature.js
  29. 35 15
      web/building_saas/main/js/views/project_view.js
  30. 24 11
      web/building_saas/main/js/views/quantity_edit_view.js
  31. 8 8
      web/building_saas/main/js/views/tender_price_view.js
  32. 2 1
      web/building_saas/pm/js/pm_newMain.js
  33. 8 1
      web/building_saas/standard_interface/config.js
  34. 16 6
      web/building_saas/standard_interface/export/anhui_chizhou.js
  35. 35 26
      web/building_saas/standard_interface/export/anhui_maanshan.js
  36. 10 0
      web/building_saas/standard_interface/export/base.js
  37. 3 2
      web/building_saas/standard_interface/import/anhui_chizhou.js
  38. 3 1
      web/building_saas/standard_interface/import/anhui_maanshan.js
  39. 27 7
      web/building_saas/standard_interface/import/base.js
  40. 2 0
      web/common/html/header.html
  41. BIN
      web/dest/css/img/more.png
  42. 75 0
      web/over_write/js/gansu_2017
  43. 14 0
      web/over_write/js/gansu_2017.js
  44. 59 61
      web/over_write/js/quanguo_2018.js
  45. 6 1
      web/users/html/user-buy.html

+ 18 - 0
config/config.js

@@ -148,6 +148,24 @@ module.exports = {
     importPort: 3050,
     socketPort: 2200
   },
+  sc_prod: {
+    title: "纵横公路云造价",
+    server: "112.74.42.187",
+    startPort: 3060,
+    dbname: 'smartcost',
+    port: "28066",
+    importPort: 3050,
+    socketPort: 2200,
+      options:{
+          user:'smartcost',
+          pass:'SmartCost3850888',
+          auth: {
+              "authdb": "admin"
+          },
+          connectTimeoutMS: 50000,
+          useMongoClient: true
+      }
+  },
   redis_local: {
     server: '127.0.0.1',
     port: '6379',

+ 2 - 1
logs/online_logs.js

@@ -25,6 +25,8 @@ async function saveOnlineTime(req) {
             return
         }
         if(!req.session.sessionUser||!req.session.sessionCompilation) return;
+        //先设置session再更新,在多个服务器多请求的情况下,update完再设置回session可能会造成多算时间
+        req.session.online_start_time = end;
         let dataString = moment(end).format('YYYY-MM-DD');
         let condition = {userID:req.session.sessionUser.id,compilationID:req.session.sessionCompilation._id,dateString:dataString};
         let userCondition = {_id: mongoose.Types.ObjectId(req.session.sessionUser.id)};
@@ -43,5 +45,4 @@ async function saveOnlineTime(req) {
         console.log("统计登录时间错误,online_times值:"+online_times);
         console.log(e)
     }
-    req.session.online_start_time = end;
 }

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

@@ -441,20 +441,15 @@ class UnitPriceModel extends BaseModel {
         }
 
         let codeList = [];
-        let nameList =[];
         for (let tmp of currentUnitList) {
             if (codeList.indexOf(tmp.code) >= 0) {
                 continue;
             }
             codeList.push(tmp.code);
-            if(nameList.indexOf(tmp.name)>=0){
-                continue
-            }
-            nameList.push(tmp.name);
         }
 
         // 查找即将更替的单价文件是否存在对应的工料机数据 -- (这里只根据code和名称初步过滤,因为其它的几项更改的概率不大,在下一步的比较中再精确匹配)
-        let condition = {unit_price_file_id: changeUnitPriceId, code: {"$in": codeList},name:{"$in": nameList}};
+        let condition = {unit_price_file_id: changeUnitPriceId, code: {"$in": codeList}};
         let targetUnitList = await this.findDataByCondition(condition, null, false, ['code','name','specs','unit','type']);
 
         // 如果没有重叠的数据则原有的数据都复制一份

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

@@ -191,7 +191,7 @@ module.exports = {
             let functionName = req.url.replace(/\//g,"");
             result.data = controller[functionName]?await controller[functionName](req):"";
         }catch (err){
-            logger.err(err);
+            logger.err(err.stack);
             if(typeof err == "string"){
                 result.error=2;
                 result.message = err;

+ 52 - 9
modules/main/facade/ration_facade.js

@@ -684,7 +684,7 @@ async function getProjectGLJinfo(projectID,t_newRationGLJList,gljKeyMap,gljCodes
   let newRationGLJList=[];
 
   let gljListModel = new GLJListModel();
-  let t_projectGLJList = await projectGLJModel.find({'project_id':projectID,'code':{'$in':gljCodes}}).lean();
+  let t_projectGLJList = await projectGLJModel.find({'project_id':projectID}).lean();
   for(let pg of t_projectGLJList){
      let pindex = getIndex(pg);  
      projectGLJMap[pindex] = pg;
@@ -727,13 +727,13 @@ async function getProjectGLJinfo(projectID,t_newRationGLJList,gljKeyMap,gljCodes
     let rkey = getIndex(ration_glj);
     let pglj = projectGLJMap[rkey];
     let subList = [];
-    setUnitPrice(pglj,unitPriceMap);
+    await setUnitPrice(pglj,unitPriceMap,ration_glj);
     if(existMixRatioMap[rkey]){//如果有组成物
       for(let m of existMixRatioMap[rkey]){
          let mpglj = projectGLJMap[getIndex(m)]
          if(mpglj){
           let cglj = _.clone(mpglj); 
-          setUnitPrice(cglj,unitPriceMap);
+          await setUnitPrice(cglj,unitPriceMap);
           cglj.ratio_data = m;
           subList.push(cglj);
          }else{
@@ -752,18 +752,60 @@ async function getProjectGLJinfo(projectID,t_newRationGLJList,gljKeyMap,gljCodes
 
 
 
-  function setUnitPrice(p,unitPriceMap){
-    p.unit_price = unitPriceMap[getIndex(p)];
+  async function setUnitPrice(p,unitPriceMap,ration_glj){
+    let unitPrice =  unitPriceMap[getIndex(p)];
+    if(unitPrice){
+      p.unit_price = unitPrice;
+    }else{
+      unitPrice = newPriceDataFromPGlj(p,unitPriceFileId);
+      if(ration_glj){
+        unitPrice.base_price = ration_glj.basePrice;
+        unitPrice.market_price = ration_glj.marketPrice;
+      }
+      await setIDfromCounter("unit_price",[unitPrice])
+      await unitPriceModel.insertMany([unitPrice]);
+      p.unit_price =unitPrice
+    }
+   
   }
 
 }
 
 
+function newPriceDataFromPGlj(np,unitPriceFileId){
+    let insertData = {
+        code: np.code,
+        base_price: np.base_price,
+        market_price: np.market_price,
+        unit_price_file_id: unitPriceFileId,
+        name: np.name,
+        specs:np.specs?np.specs:'',
+        original_code:np.original_code,
+        unit:np.unit?np.unit:'',
+        type: np.type,
+        short_name: np.shortName !== undefined ? np.shortName : '',
+        glj_id: np.glj_id,
+        is_add:0,
+        grossWeightCoe:np.grossWeightCoe,
+        purchaseStorageRate:np.purchaseStorageRate,
+        offSiteTransportLossRate:np.offSiteTransportLossRate,
+        handlingLossRate:np.handlingLossRate
+      };
+      if(np.code == '80CCS'){//车船税默认价格为1
+          insertData.base_price = '1';
+          insertData.market_price = '1';
+      }
+      if(np.from=='cpt') insertData.is_add=1;//如果是来自补充工料机,则都添加新增标记
+      if(insertData.code != insertData.original_code) insertData.is_add=1;//添加的时候如果是复制整块来的,可能在源项目中是新增的工料机,这里也要添上(暂时可能还用不到)
+    return insertData;
+  }
+  
+
 //找到并返回单价文件信息,如果没有自动插入
 async function getUnitPriceData(newProjectGLJList,gljCodes,unitPriceFileId){
   let unitPriceMap = {};
   let newUnitPriceList = [];
-  let unitPriceList = await unitPriceModel.find({unit_price_file_id: unitPriceFileId,'code':{'$in':gljCodes}}).lean();
+  let unitPriceList = await unitPriceModel.find({unit_price_file_id: unitPriceFileId}).lean();
   for(let u of unitPriceList){
     unitPriceMap[getIndex(u)]=u;
   }
@@ -771,7 +813,9 @@ async function getUnitPriceData(newProjectGLJList,gljCodes,unitPriceFileId){
   for(let np of newProjectGLJList){
     let pkey = getIndex(np);
     if(unitPriceMap[pkey]) continue;
-    let insertData = {
+    let insertData = newPriceDataFromPGlj(np,unitPriceFileId);
+    
+    /* {
       code: np.code,
       base_price: np.base_price,
       market_price: np.market_price,
@@ -794,12 +838,11 @@ async function getUnitPriceData(newProjectGLJList,gljCodes,unitPriceFileId){
         insertData.market_price = '1';
     }
     if(np.from=='cpt') insertData.is_add=1;//如果是来自补充工料机,则都添加新增标记
-    if(insertData.code != insertData.original_code) insertData.is_add=1;//添加的时候如果是复制整块来的,可能在源项目中是新增的工料机,这里也要添上(暂时可能还用不到)
+    if(insertData.code != insertData.original_code) insertData.is_add=1;//添加的时候如果是复制整块来的,可能在源项目中是新增的工料机,这里也要添上(暂时可能还用不到) */
     newUnitPriceList.push(insertData);
     unitPriceMap[pkey] = insertData;
   }
 
-
   if(newUnitPriceList.length > 0){
     await setIDfromCounter("unit_price",newUnitPriceList);
     await unitPriceModel.insertMany(newUnitPriceList);

+ 17 - 0
modules/pm/controllers/pm_controller.js

@@ -13,6 +13,7 @@ let projType = require('../models/project_model').projType;
 let fileType = require('../models/project_model').fileType;
 const engineering = require("../../common/const/engineering");
 let EngineeringLibModel = require("../../users/models/engineering_lib_model");
+const engineeringModel = mongoose.model('engineering_lib');
 let fee_rate_facade = require("../../fee_rates/facade/fee_rates_facade");
 let billsModel = require('../../main/models/bills').model;
 let rationsModel = require('../../main/models/ration').model;
@@ -128,6 +129,22 @@ module.exports = {
                 }
                 delete datas.properties['property.basicInformation'];
             }
+            // 工程特征特殊处理
+            if (datas.properties['property.projectFeature']) {
+                const engineeringItem = _.find(datas.properties['property.projectFeature'], { key: 'engineering' });
+                const feeStandardItem = _.find(datas.properties['property.projectFeature'], { key: 'feeStandard' });
+                if (engineeringItem && engineeringItem.value && feeStandardItem && feeStandardItem.value) {
+                    const project = await projectModel.findOne({ ID: datas.projectID }, { 'property.valuation': 1 }).lean();
+                    if (project) {
+                        const engineering = await engineeringModel.findOne({ valuationID: project.property.valuation, name: engineeringItem.value, feeName: feeStandardItem.value }, { _id: 1 }).lean();
+                        if (engineering) {
+                            datas.properties['property.engineeringName'] = engineeringItem.value;
+                            datas.properties['property.feeStandardName'] = feeStandardItem.value;
+                            datas.properties['property.engineering_id'] = engineering._id.toString();
+                        }
+                    }
+                }
+            }
             functions.push(updateFunc(projectModel, { ID: datas.projectID }, datas.properties));
         };
 

+ 29 - 1
modules/pm/facade/pm_facade.js

@@ -1462,7 +1462,7 @@ async function getFullPath(projectID) {
 }
 
 //@param {String}libID(工程特征库ID) {Object}assign(需要赋值的key-value)
-async function getProjectFeature(libID, assign) {
+async function getProjectFeature(libID, valuationID, assign) {
     let lib = await featureLibModel.findOne({'ID':libID});
     if (lib) {
         for (let key in assign) {
@@ -1471,6 +1471,34 @@ async function getProjectFeature(libID, assign) {
                 obj.value = assign[key];
             }
         }
+        // 特殊处理养护类别和费用标准
+        const engineeringItem = _.find(lib.feature, { key: 'engineering' });
+        const feeStandardItem = _.find(lib.feature, { key: 'feeStandard' });
+        if ((!engineeringItem || engineeringItem.readOnly === 'true') && (!feeStandardItem || feeStandardItem.readOnly === 'true')) {
+            return lib.feature;
+        }
+        const engs = await engineeringModel.find({ valuationID }, { name: 1, feeName: 1 }).lean();
+        const engOptions = [];
+        const feeStandardOptions = {};
+        engs.forEach(item => {
+            const name = item.name ? item.name : '';
+            const feeName = item.feeName ? item.feeName : '';
+            if (!engOptions.includes(name)) {
+                engOptions.push(name);
+            }
+            if (!feeStandardOptions[name]) {
+                feeStandardOptions[name] = [];
+            }
+            if (!feeStandardOptions[name].includes(feeName)) {
+                feeStandardOptions[name].push(feeName);
+            }
+        });
+        if (engineeringItem && engineeringItem.readOnly === 'false') {
+            engineeringItem.options = engOptions.join('@');
+        }
+        if (feeStandardItem && feeStandardItem.readOnly === 'false') {
+            feeStandardItem.relatedOptions = JSON.stringify(feeStandardOptions);
+        }
         return lib.feature;
 
     } else {

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

@@ -207,7 +207,7 @@ ProjectsDAO.prototype.updateUserProjects = async function (userId, compilationId
                             // 新建分段文件时,默认将“工程特征”-“单项工程名称”填写建设项目名称
                             singleProjName: constructionProjectName,
                         };
-                        data.updateData.property.projectFeature = await pmFacade.getProjectFeature(data.updateData.property.featureLibID, assign);
+                        data.updateData.property.projectFeature = await pmFacade.getProjectFeature(data.updateData.property.featureLibID, data.updateData.property.valuation, assign);
                     }
                     /*projectFeature[0]['value'] = data.updateData.property.engineeringName || '';
                     data.updateData.property.projectFeature = projectFeature;*/

+ 2 - 2
modules/users/controllers/cld_controller.js

@@ -111,8 +111,8 @@ class CLDController {
         let compilationID = request.body.cid;
         let deadline = request.body.deadline || '';
         let status = parseInt(request.body.status);
-        let smssend = parseInt(request.body.smssend);
-        let lock = parseInt(request.body.lock);// 0.默认、1.借出(借用)、2.销售(购买)
+        let smssend = parseInt(request.body.smssend) || 0;
+        let lock = parseInt(request.body.lock) || 0;// 0.默认、1.借出(借用)、2.销售(购买)、3.赠送(借用)
         try {
 
             let userModel = new UserModel();

+ 37 - 18
public/web/gljUtil.js

@@ -327,9 +327,15 @@ let gljUtil = {
       let constCoe = scMathUtil.roundForObj(projectGLJDatas.constData.machineConstCoe,feeRate_decimal);
       for (let ratio of glj.ratio_data) {
         let rIndex = gljUtil.getIndex(ratio);
-        let tem = _.find(projectGLJDatas.gljList, function (item) {
-          return rIndex == gljUtil.getIndex(item);
-        });
+        let tem = null;
+        if(projectGLJDatas.gljMap){
+          tem = projectGLJDatas.gljMap[rIndex]
+        }
+        if(!tem){
+          tem = _.find(projectGLJDatas.gljList, function (item) {
+            return rIndex == gljUtil.getIndex(item);
+          });
+        }
         if (tem) {
           let tem_marketPrice = this.getMarketPrice(tem, projectGLJDatas, calcOptions, labourCoeDatas, decimalObj, true, _, scMathUtil);
           if (ext && ext[tem.id] && this.isDef(ext[tem.id].marketPrice)) { //在修改组成物的价格或消耗量时,影响了父工料机的价格,这时以父工料机的价格应当用组成物的新值来记算
@@ -395,17 +401,20 @@ let gljUtil = {
         'ID': glj.adjCoe
       });
       let coe = labour && labour.coe ? labour.coe : 1;
-      return scMathUtil.roundTo(parseFloat(coe * scMathUtil.roundForObj(glj.unit_price.base_price, decimal)), -decimal);
+      return scMathUtil.roundForObj(coe * scMathUtil.roundForObj(glj.unit_price.base_price, decimal), decimal);
     } else if (this.notEditType.indexOf(glj.unit_price.type) != -1 && glj.ratio_data.length > 0) { //对于混凝土、配合比、砂浆、机械台班,调整价根据组成物计算得出。
       let p = 0;
       for (let ratio of glj.ratio_data) {
-        let tem = _.find(projectGLJDatas.gljList, {
-          'code': ratio.code,
-          'name': ratio.name,
-          'specs': ratio.specs,
-          'type': ratio.type,
-          'unit': ratio.unit
-        })
+        let rIndex = gljUtil.getIndex(ratio);
+        let tem = null;
+          if(projectGLJDatas.gljMap){
+            tem = projectGLJDatas.gljMap[rIndex]
+        }
+        if(!tem){
+          tem =  _.find(projectGLJDatas.gljList,function(item){
+              return rIndex == gljUtil.getIndex(item);
+          });
+        }
         if (tem) {
           let priceData = this.getGLJPrice(tem, projectGLJDatas, calcOptions, labourCoeDatas, decimalObj, true, _, scMathUtil);
           let temP = scMathUtil.roundForObj(priceData.adjustPrice * scMathUtil.roundForObj(ratio.consumption, quantity_decimal), process_decimal);
@@ -435,16 +444,26 @@ let gljUtil = {
   isDef: function (v) {
     return v !== undefined && v !== null;
   },
+
+  nullString(key){
+    return (key === undefined || key === null || key === '') ? 'null' : key
+  },
+
+
   getIndex(obj, pops) {
     let t_index = '';
     let k_arr = [];
-    if (!this.isDef(pops)) pops = this.gljKeyArray;
-    for (let p of pops) {
-      let tmpK = (obj[p] == undefined || obj[p] == null || obj[p] == '') ? 'null' : obj[p];
-      k_arr.push(tmpK);
+    if(!pops) pops = this.gljKeyArray;
+    if(pops.length === 5){
+        return `${this.nullString(obj[pops[0]])}|-|${this.nullString(obj[pops[1]])}|-|${this.nullString(obj[pops[2]])}|-|${this.nullString(obj[pops[3]])}|-|${this.nullString(obj[pops[4]])}`
+    }else{
+        for (let p of pops) {
+            let tmpK = (obj[p] == undefined || obj[p] == null || obj[p] == '') ? 'null' : obj[p];
+            k_arr.push(tmpK);
+        }
+        t_index = k_arr.join("|-|");
+        return t_index;
     }
-    t_index = k_arr.join("|-|");
-    return t_index;
   },
 
   getMainType: function (type) {
@@ -580,7 +599,7 @@ let gljUtil = {
       let pglj = calcTools.getProjectGLJ(glj);
       glj.tenderQuantity = this.getRationGLJTenderQuantity(glj, ration, gd, scMathUtil, pglj);
 
-      return scMathUtil.roundToString(quantity * glj.quantity, gd);
+      return scMathUtil.roundForObj(quantity * glj.quantity, gd)+'';
     }
   },
   setMaterialCalcRationFee: function (ration, ration_gljs, projectGLJDatas, calcOptions, labourCoeDatas, decimalObj, _, scMathUtil) {

+ 34 - 9
public/web/scMathUtil.js

@@ -170,19 +170,41 @@ let scMathUtil = {
     isNumber : function (obj) {
         return obj === +obj;
     },
+    floatLength:function(num){
+        let lenght = 0;
+        let str =`${num}`;
+        let sub = str.split(".")
+        if(sub.length == 2){
+            return sub[1].length;
+        }
+        return lenght
+    },
+    innerRound:function(num,lenght,decimal){
+        let value;
+        let pre = 1;
+        if(lenght === 0) return num;
+        if(num<0) pre = -1;//负数的时候先变成正数
+        num = num*pre;
+        let n = Math.pow(10,lenght);
+        value = Math.round(num * n)
+        if(lenght <= decimal){
+            return value/n*pre
+        }else{
+            value = Math.round(value/Math.pow(10,lenght-decimal))
+            return value/Math.pow(10,decimal)*pre
+        }
+    },
     roundForObj:function(obj,decimal){
         let me = this;
-        let value;
         if(obj === undefined || obj === null || isNaN(obj)) return 0;
-        let n = Math.pow(10,decimal);
+        let lenght = 10 ;
+        let value;
         if(me.isNumber(obj)){
-          value = Math.round(obj * n) / n;
-          //value = me.roundTo(obj,-decimal)
-        }else {
-          value = Math.round(Number(obj) * n) / n;
-          //value = me.roundTo(Number(obj),-decimal);
+            value =  me.innerRound(obj,lenght,decimal);
+        }else{
+            value = me.innerRound(Number(obj),lenght,decimal);
         }
-        return value
+        return value;
     },
     roundToString:function(obj,decimal){
         let me = this;
@@ -223,5 +245,8 @@ Number.prototype.toDecimal = function (ADigit) {
     // var s = scMathUtil.roundTo(this, digit);
     // console.log('Number: ' + this + '   Digit: ' + digit + '    Result: ' + s);
     // return parseFloat(s);
-    return scMathUtil.roundTo(this, digit);
+    //scMathUtil.roundTo(this, digit);
+   
+    
+    return scMathUtil.roundForObj(this, -digit);
 };

+ 35 - 0
public/web/sheet/sheet_data_helper.js

@@ -384,5 +384,40 @@ var SheetDataHelper = {
                 }
             }
         }
+    },
+    setMoreButtonPos:function(button,sheet,cellRect){
+        let pos = SheetDataHelper.getObjPos(sheet.getParent().qo);
+        let headerHeight = sheet.getRowHeight(0,GC.Spread.Sheets.SheetArea.colHeader)
+        if(cellRect.y === undefined){//如果没有即滚动到超出了视图范围,设置到看不见的位置
+            button.css("top", -1000)
+        }else{
+            button.css("top", pos.y+cellRect.y-headerHeight-15).css("left", pos.x+cellRect.x+cellRect.width);
+        }
+        
+    },
+
+    showMoreButton:function(hitinfo,callback){
+        let sheet = hitinfo.sheet;
+        if(sheet && sheet.getParent().qo){
+            let button = $('.moreButton');
+            button.unbind('click');
+            button.bind('click',function(){
+                callback(hitinfo.row);
+            })
+            this.setMoreButtonPos(button,sheet,hitinfo.cellRect);
+            button.show();
+        }
+    },
+
+    hideMoreButton:function(){
+        $('.moreButton').hide();
+    },
+    moveMoreButton:function(sheet,newTopRow){
+        let button = $('.moreButton');
+        if(button.is(':visible')){
+            let cellRect = sheet.getCellRect(sheet.getActiveRowIndex(), sheet.getActiveColumnIndex());
+            this.setMoreButtonPos(button,sheet,cellRect)
+        }
+       
     }
 };

+ 11 - 5
public/web/syntax-detection.js

@@ -1,4 +1,4 @@
-/** 
+/**
  * 浏览器兼容性,特性检查
  * 参考列表: http://kangax.github.io/compat-table/es6/
  * 同内核的不同的浏览器需要处理,比如qq浏览器登陆成功后,ie浏览器登陆页面会自动跳转到项目管理页面。因此项目管理页面也需要检测
@@ -151,7 +151,7 @@ function checkSyntax() {
         }
 
         // DOM
-        if (typeof document.documentElement.requestFullscreen !== 'function' && 
+        if (typeof document.documentElement.requestFullscreen !== 'function' &&
             typeof document.documentElement.mozRequestFullscreen !== 'function' &&
             typeof document.documentElement.webkitRequestFullscreen !== 'function' &&
             typeof document.documentElement.msRequestFullscreen !== 'function') {
@@ -170,7 +170,7 @@ function showBrowserTip() {
         '<div class="modal-dialog modal-lg" role="document">' +
         '<div class="modal-content">' +
         '<div class="modal-body">' +
-        '<h5>浏览器版本过低,可能会有安全风险;</h5>' +
+        '<h5>浏览器版本过低</h5>' +
         '<h5>请更新 「浏览器」 或者 使用 「纵横Z+造价工作平台」 登录。</h5>' +
         '<div class="row my-4">' +
         '<div class="col-6">' +
@@ -178,7 +178,13 @@ function showBrowserTip() {
         '</div>' +
         '<div class="col-6">' +
         '<div class="text-center"><a href="https://smartcost.com.cn/downloadzplus" class="btn btn-primary" target="_blank">下载 纵横Z+造价工作平台</a></div>' +
-        '</div></div></div></div></div></div>';
+        '</div>' +
+        '</div>' +
+        '</div>' +
+        '<div class="modal-footer">' +
+        '<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>' +
+        '</div>'
+    '</div></div></div>';
     $('body').append(html);
     $('#browser').modal('show');
 }
@@ -191,4 +197,4 @@ $(document).ready(function () {
         showBrowserTip();
         return false;
     }
-});
+});

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

@@ -824,4 +824,13 @@ color:#666;
 font-size: 16px;
 margin-bottom:0;
 color:#333;
+}
+
+.moreButton{
+  position: absolute;
+  cursor: pointer;
+}
+.moreImg{
+  width: 15px;
+  height: 15px;
 }

BIN
web/building_saas/img/vip3.png


+ 12 - 0
web/building_saas/js/global.js

@@ -163,6 +163,18 @@ function replaceAll(FindText, RepText,str) {
     return str.replace(regExp, RepText);
 };
 
+//求余处理成百分号,即乘以0.01
+function handlePercent(text){
+    let arr = text.match(/[\d^%]+%/g);
+    if(arr){
+        for(let str of arr){
+            let tem = str.replace("%"," * 0.01");
+            text = text.replace(str,`${(tem)}`)
+        }
+    }
+    return text
+}   
+
 function setTimeoutSync(handle, time) {
     return new Promise(function(resolve, reject) {
         setTimeout(function () {

+ 4 - 2
web/building_saas/main/html/main.html

@@ -186,6 +186,9 @@
                       <div class="main-content" style="width: 100%; display: inline-block" id="main">
                           <div class="top-content" id="top_div" style="overflow:hidden;">
                               <div class="main-data-top" id="billsSpread"></div>
+                              <div class="moreButton" style="display: none">
+                                <img src="/web/dest/css/img/more.png" class="moreImg"></img>
+                              </div>
                           </div>
                           <div class="resize-y" id="mainVerticalResize"></div>
                           <div class="bottom-content" id="bottom_div">
@@ -809,7 +812,6 @@
                                             </div>
 
                                         </fieldset>
-                                        <% if (!projectData.importedByInterface) { %>
                                             <fieldset class="form-group">
                                               <h5>清单限价</h5>
                                               <div class="mt-1">
@@ -819,7 +821,6 @@
                                                 <span data-toggle="tooltip" data-placement="bottom" data-original-title="最低限价=清单综合单价*(1-X%)">最低限价 </span><input id="min-price-rate" data-limit="min" class="form-control form-control-sm limit-price-input" value="0" type="text"> %
                                             </div>
                                             </fieldset>
-                                            <% } %>
                                     </div>
                                 </div>
                                 <!--清单工程精度-->
@@ -1735,6 +1736,7 @@
                             <button class="btn btn-secondary btn-sm" >/</button>
                             <button class="btn btn-secondary btn-sm" >(</button>
                             <button class="btn btn-secondary btn-sm" >)</button>
+                            <button class="btn btn-secondary btn-sm">%</button>
                         </p>
                     </div>
                     <div class="row" >

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

@@ -458,7 +458,7 @@ let BlockController = {
 
     preparePasteData : function (datas,billsIDMap,firstParentID,lastNextID) {
         let me = this;
-        me.datas = _.cloneDeep(projectObj.project.Bills.datas);
+        me.datas = _.clone(projectObj.project.Bills.datas);
         let bills = [],rations=[],ration_gljs = [],ration_coes = [],quantity_details = [],ration_installations = [],ration_templates=[];
         let firstBillIDs = [],lastBillID = null;//记录第一层清单的ID,和第一层的最后一个清单ID
         let firstIDMap = {};

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

@@ -30,9 +30,14 @@ $(function () {
     });
 
     $('#tab_report').on('shown.bs.tab', function(e){
-        projectObj.project.calcProgram.doTenderCalc();   // 进入报表前先自动调价计算一遍
         sessionStorage.setItem('mainTab', '#tab_report');
         autoFlashHeight();
+        $.bootstrapLoading.start();
+        setTimeout(function(){
+            projectObj.project.calcProgram.doTenderCalc();   // 进入报表前先自动调价计算一遍
+            $.bootstrapLoading.end();
+        }, 100);
+
     });
     let mainResizeEles = getMainResizeEles();
     SlideResize.verticalSlide(mainResizeEles.eleObj, mainResizeEles.limit, function(){

+ 22 - 3
web/building_saas/main/js/models/calc_base.js

@@ -548,6 +548,23 @@ let cbTools = {
     fee += (baseFee - withinData.min) * withinData.feeRate * 0.01;
     return fee.toDecimal(decimalObj.bills.totalPrice);
   },
+  // 获取设备购置费
+  getEquipmentFee(fixedNode, tender, feeField = 'common') {
+    const allSubNodes = [];
+    projectObj.project.mainTree.getAllSubNode(fixedNode, allSubNodes);
+    const equipmentNodes = allSubNodes.filter(node => node.data.type === rationType.gljRation && node.data.subType === gljType.EQUIPMENT);
+    const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
+    let totalEquipmentFee = 0;
+    for (const node of equipmentNodes) {
+      const data = node.data;
+      if (this.isUnDef(data.feesIndex) || _.isEmpty(data.feesIndex) ||
+      this.isUnDef(data.feesIndex[feeField]) || this.isUnDef(data.feesIndex[feeField][subFeeField])) {
+        continue;
+      }
+      totalEquipmentFee = (totalEquipmentFee + data.feesIndex[feeField][subFeeField]).toDecimal(decimalObj.process);
+    }
+    return totalEquipmentFee;
+  },
   //获取清单100章下的节点(只需要找最底层的,排除了底层,父项金额即排除了子项)
   //@param {Object}node(判断的节点,最底层清单节点)
   //@return {Boolean}
@@ -982,7 +999,7 @@ let cbAnalyzer = {
   },
   //输入合法性
   inputLegal: function (exp) {
-    let ilegalRex = /[^0-9,\u4e00-\u9fa5,\+,\-,\/,\*,\(,\),.,{,},F,%]/g;
+    let ilegalRex = /[^0-9,\u4e00-\u9fa5,\+,\-,\/,\*,\(,\),.,{,},F,%]/g;
     return !ilegalRex.test(exp);
   },
   //基数合法性、存在性
@@ -1178,7 +1195,7 @@ let cbParser = {
   },
   //获取表达式中的中文式
   getCN: function (expr) {
-    let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}[\u4e00-\u9fa5]{0,}\d*%*[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}/g;
+    let cnRex = /\d*[\u4e00-\u9fa5]{1,}\({0,}[\u4e00-\u9fa5]{0,}\*?\d*%*、?[\u4e00-\u9fa5]{0,}\){0,}[\u4e00-\u9fa5]{0,}/g;
     return _.filter(expr.match(cnRex), function (data) {
       return data
     });
@@ -1214,7 +1231,8 @@ let cbParser = {
   },
   //表达式中的百分数转换成小数
   percentToNum: function (exp) {
-    let rex = /[\+,\-,\*,\/]{1}\d+(\.\d+)?%[\u4e00-\u9fa5]{0}/g;
+    // let rex = /[\+,\-,\*,\/]{1}\d+(\.\d+)?%[\u4e00-\u9fa5]{0}\'{0}\){0}/g;
+    let rex = /[\+,\-,\*,\/]{1}\d+(\.\d+)?%(?![\u4e00-\u9fa5]|\))/g;
     let percents = exp.match(rex);
     let numRex = /\d+(\.\d+)?/g;
     if (cbTools.isDef(percents)) {
@@ -1297,6 +1315,7 @@ let cbParser = {
       exps[i].compileExp = '$CBC.base(\'' + exps[i].orgExp + '\')';
       let regStr = exps[i].orgExp.replace(/\(/g, '\\\(');
       regStr = regStr.replace(/\)/g, '\\\)');
+      regStr = regStr.replace(/\*/g, '\\\*');
       v = v.replace(new RegExp(regStr, 'g'), exps[i].compileExp);
     }
     //去{}

Dosya farkı çok büyük olduğundan ihmal edildi
+ 3240 - 2506
web/building_saas/main/js/models/calc_program.js


Dosya farkı çok büyük olduğundan ihmal edildi
+ 95 - 95
web/building_saas/main/js/models/feeRateConsts.js


+ 5 - 0
web/building_saas/main/js/models/project_glj.js

@@ -75,6 +75,10 @@ ProjectGLJ.prototype.synLoadData = function () {
 
 ProjectGLJ.prototype.loadToCache = function (data) {
     this.datas = data;
+    this.datas.gljMap =  {};
+    for(let g of this.datas.gljList){
+       this.datas.gljMap[gljUtil.getIndex(g)]=g;
+    }
 }
 
 
@@ -1780,6 +1784,7 @@ ProjectGLJ.prototype.loadNewProjectGLJToCache = function (data,tIDMap) {//把新
     let uIndex = gljUtil.getIndex(data.unit_price);
     if(!unitPriceMap[uIndex])  unitPriceMap[uIndex] = data.unit_price;
     this.datas.gljList.push(data);
+    this.datas.gljMap[gljUtil.getIndex(data)]= data;
     IDMap[data.id] = data;
     return data;
 };

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

@@ -88,7 +88,7 @@ let ration_glj = {
                 }
             }
 
-            result = gljOprObj.combineWithProjectGlj(result);
+            result = gljOprObj.combineWithProjectGlj(result,false);
 
             if (!needOneBill) return result;
 

+ 9 - 9
web/building_saas/main/js/views/glj_col.js

@@ -10,14 +10,14 @@ let gljCol = {
             {headerName: "单位", headerWidth: 45, dataCode: "unit", dataType: "String", hAlign: "center"},
             {headerName: "预算价", headerWidth: 65, dataCode: "marketPrice", dataType: "Number", validator:"number",hAlign: "right"},//, decimalField: "glj.unitPrice"
             {headerName: "调整价", headerWidth: 65, dataCode: "adjustPrice", dataType: "Number",validator:"number", hAlign: "right"},//, decimalField: "glj.unitPrice"1
-            {headerName: "自定消耗", headerWidth: 65, dataCode: "customQuantity", dataType: "Number",validator:"number", hAlign: "right", decimalField: "glj.quantity"},
-            {headerName: "消耗量", headerWidth: 65, dataCode: "quantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity"},
+            {headerName: "自定消耗", headerWidth: 65, dataCode: "customQuantity", dataType: "Number",validator:"number", hAlign: "right"},
+            {headerName: "消耗量", headerWidth: 65, dataCode: "quantity", dataType: "Number", hAlign: "right"},
             {headerName: "定额价", headerWidth: 65, dataCode: "basePrice", dataType: "Number", hAlign: "right"},//, decimalField: "glj.unitPrice"
-            {headerName: "定额消耗", headerWidth: 65, dataCode: "rationItemQuantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity"},   // dataType: "Number", formatter: "0.00"
-            {headerName: "总消耗量", headerWidth: 80, dataCode: "totalQuantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity"},
+            {headerName: "定额消耗", headerWidth: 65, dataCode: "rationItemQuantity", dataType: "Number", hAlign: "right"},   // dataType: "Number", formatter: "0.00"
+            {headerName: "总消耗量", headerWidth: 80, dataCode: "totalQuantity", dataType: "Number", hAlign: "right"},
             // {headerName: "暂估", headerWidth: 45, dataCode: "isEstimate", dataType: "String", hAlign: "center", vAlign: "center", cellType: "checkBox"},
             {headerName: "调后预算价", headerWidth: 80, dataCode: "tenderPrice", dataType: "Number", hAlign: "right", visible: false},
-            {headerName: "调后消耗量", headerWidth: 80, dataCode: "tenderQuantity", dataType: "Number", hAlign: "right", decimalField: "glj.quantity", visible: false}
+            {headerName: "调后消耗量", headerWidth: 80, dataCode: "tenderQuantity", dataType: "Number", hAlign: "right", visible: false}
         ],
         view: {
             lockColumns: [ "adjustPrice", "rationItemQuantity", "quantity", "totalQuantity", "isEstimate", "tenderPrice", "tenderQuantity"],
@@ -245,7 +245,7 @@ let gljCol = {
             setting.view.lockColumns = newArray;
         }
     },
-    initGljCol:function (showAdjustPrice, showTenderFields) {
+    initGljCol:function (showAdjustPrice, showTenderFields,init=false) {
         let me = gljCol;
         if(showAdjustPrice !== true){
             me.removeCol('adjustPrice',me.ration_glj_setting);
@@ -256,14 +256,14 @@ let gljCol = {
             me.removeCol('is_adjust_price',me.project_glj_setting);
         }
         
-	me.showTenderFields(showTenderFields, false);
+	me.showTenderFields(showTenderFields, false,init);
 	gljOprObj.setting = me.ration_glj_setting;
         projectGljObject.projectGljSetting = me.project_glj_setting;
         projectGljObject.mixRatioSetting = me.mixRatio_Setting;
         me.setScopeFormater();
         gljOprObj.scopeSetting = me.scopeSetting;
     },
-    showTenderFields: function (showFields = false, needRefresh = false){
+    showTenderFields: function (showFields = false, needRefresh = false,init=false){
         let me = gljCol;
 
         let PGLJHeader = me.project_glj_setting.header;
@@ -289,7 +289,7 @@ let gljCol = {
 
         colSettingObj.setVisible('feesIndex.common.tenderUnitFee', showFields);
         colSettingObj.setVisible('feesIndex.common.tenderTotalFee', showFields);
-        colSettingObj.updateColSetting(true);
+        colSettingObj.updateColSetting(true,init);
 
         if (needRefresh){
             if(projectGljObject.projectGljSpread) {

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

@@ -693,7 +693,7 @@ var gljOprObj = {
     calcMixRationTotalQuantity(mList,pTotal){ //计算组成物的总消耗量
         for (let subG of mList) {
             subG.rationItemQuantity = scMathUtil.roundForObj(subG.rationItemQuantity, getDecimal("glj.quantity"));
-            subG.totalQuantity = scMathUtil.roundToString(subG.rationItemQuantity * pTotal, getDecimal("glj.quantity"));
+            subG.totalQuantity = scMathUtil.roundForObj(subG.rationItemQuantity * pTotal, getDecimal("glj.quantity"))+'';
         }
     },
     addMixRatioToShow: function () {
@@ -738,7 +738,7 @@ var gljOprObj = {
                     if(ration) gljOprObj.getTotalQuantity(ration_gljs[i], ration);
                 }else {
                     //计算程序中量价也会放到这里进来,量价是没有对应的项目工料机的
-                    if(ration_gljs[i].type != rationType.volumePrice) console.log("没有找到工料机:"+ration_gljs[i].name)
+                    //if(ration_gljs[i].type != rationType.volumePrice) console.log("没有找到工料机:"+ration_gljs[i].name)
                 }
             }
         }
@@ -801,9 +801,16 @@ var gljOprObj = {
         var temRationGLJs = [];
         for (var i = 0; i < mixRatioList.length; i++) {
             let mIndex = gljOprObj.getIndex(mixRatioList[i],gljKeyArray);
-            var pg = _.find(projectGljs, function (item) {
-                return gljOprObj.getIndex(item,gljKeyArray) == mIndex
-            });//改关联关系
+            let pgljMap = projectObj.project.projectGLJ.datas.gljMap;
+            let pg = null;
+            if(pgljMap){
+                pg = pgljMap[mIndex];
+            }
+            if(!pg){
+                pg = _.find(projectGljs, function (item) {
+                    return gljOprObj.getIndex(item,gljKeyArray) == mIndex
+                });//改关联关系
+            }
             if(pg){
                 let tem = {
                     projectGLJID: pg.id,

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

@@ -296,12 +296,12 @@ let MainTreeCol = {
     },
     maxPrice: function (node) {
       const hasOutPutMaxPriceCol = !!projectObj.project.projSetting.main_tree_col.cols.find(item => item.data.field === 'outPutMaxPrice');
-      const hasOutPutLitmitPriceCol = !!projectObj.project.projSetting.main_tree_col.cols.find(item => item.data.field === 'outPutLitmitPrice');
-      return projectObj.project.projectInfo.importedByInterface || (hasOutPutMaxPriceCol && (node.data.outPutMaxPrice === undefined || node.data.outPutMaxPrice === false)) || (hasOutPutLitmitPriceCol && (node.data.outPutLimitPrice === undefined || node.data.outPutLimitPrice === false));
+      const hasOutPutLimitPriceCol = !!projectObj.project.projSetting.main_tree_col.cols.find(item => item.data.field === 'outPutLimitPrice');
+      return (hasOutPutMaxPriceCol && (node.data.outPutMaxPrice === undefined || node.data.outPutMaxPrice === false)) || (hasOutPutLimitPriceCol && (node.data.outPutLimitPrice === undefined || node.data.outPutLimitPrice === false));
     },
     minPrice: function (node) {
-      const hasOutPutLitmitPriceCol = !!projectObj.project.projSetting.main_tree_col.cols.find(item => item.data.field === 'outPutLitmitPrice');
-      return projectObj.project.projectInfo.importedByInterface || (hasOutPutLitmitPriceCol && (node.data.outPutLimitPrice === undefined || node.data.outPutLimitPrice === false));
+      const hasOutPutLimitPriceCol = !!projectObj.project.projSetting.main_tree_col.cols.find(item => item.data.field === 'outPutLimitPrice');
+      return (hasOutPutLimitPriceCol && (node.data.outPutLimitPrice === undefined || node.data.outPutLimitPrice === false));
     },
   },
   cellType: {
@@ -415,14 +415,14 @@ let MainTreeCol = {
     },
     outPutMaxPrice: function (node) {
       if (node.sourceType === projectObj.project.Bills.getSourceType()) {
-        return projectObj.project.projectInfo.importedByInterface  || projectObj.project.projectInfo.property.lockBills
+        return projectObj.project.projectInfo.property.lockBills
           ? sheetCommonObj.getReadOnlyCheckBox()
           : sheetCommonObj.getCheckBox();
       }
     },
     outPutLimitPrice: function (node) {
       if (node.sourceType === projectObj.project.Bills.getSourceType()) {
-        return projectObj.project.projectInfo.importedByInterface || projectObj.project.projectInfo.property.lockBills
+        return projectObj.project.projectInfo.property.lockBills
           ? sheetCommonObj.getReadOnlyCheckBox()
           : sheetCommonObj.getCheckBox();
       }
@@ -615,7 +615,7 @@ let colSettingObj = {
     }
     return false;
   },
-  updateColSetting: function (skipSetValue = false) {
+  updateColSetting: function (skipSetValue = false,init=false) {
     let mainSheet = projectObj.mainSpread.getActiveSheet();
     if (!skipSetValue) {
       let sheet = this.settingSpread.getActiveSheet();
@@ -630,7 +630,7 @@ let colSettingObj = {
       mainSheet.showColumn(projectObj.project.projSetting.mainGridSetting.frozenCols, GC.Spread.Sheets.HorizontalPosition.left);
     });
     //refresh nodes to autoFitRow
-    projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots, true);
+    if(init === false) projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots, true);
     if (!skipSetValue) {
       //列设置将项目特征和工作内容都取消打钩后,更新快速列设置
       if (!this.getVisible('itemCharacterText')) {

+ 56 - 4
web/building_saas/main/js/views/project_property_projFeature.js

@@ -108,8 +108,7 @@ let projFeatureView = {
             me.initTree(sheet, true, datas);
             sheet.setFormatter(-1, 1, '@');
             //兼容旧数据
-            let compatLockedKeys = ['engineering'],
-                compatNumKeys = [
+            let compatNumKeys = [
                     'buildingArea',
                     'basementBuildingArea',
                     'totalFloors',
@@ -122,8 +121,20 @@ let projFeatureView = {
                     'standardFloorHeight'
                 ];
             for(let row = 0;row < datas.length ; row ++){
+                console.log(datas[row]);
                 if(datas[row].cellType == 'comboBox'){
-                    let options = datas[row].options?datas[row].options.split("@"):[];
+                    let options = [];
+                    if (datas[row].options) {
+                        options = datas[row].options.split("@")
+                    } else if (datas[row].relatedOptions) {
+                        const eng = datas.find(item => item.key === 'engineering');
+                        const engValue = eng.value || '';
+                        const relatedOptions = JSON.parse(datas[row].relatedOptions);
+                        options = relatedOptions[engValue] || [];
+                    } else {
+                        options = [];
+                    }
+                    // let options = datas[row].options?datas[row].options.split("@"):[];
                     me.setCombo(sheet, row, options);
                 } else if(datas[row].cellType == 'number' || compatNumKeys.includes(datas[row].key)){
                     me.setting.numRows.push(row);
@@ -131,7 +142,7 @@ let projFeatureView = {
                     me.setting.dateRows.push(row);
                 }
                 let readOnly = typeof datas[row].readOnly === 'string' ? JSON.parse(datas[row].readOnly) : datas[row].readOnly;
-                if (readOnly || datas[row].items || compatLockedKeys.includes(datas[row].key)) {
+                if (readOnly || datas[row].items) {
                     me.setting.locked.rows.push(row);
                 }
                 for(let col = 0;col < cols.length;col++){
@@ -177,6 +188,19 @@ let projFeatureView = {
                     }
                 }
             }
+            // 特殊处理养护类别和费用标准
+            const item = me.datas[args.row];
+            if (item.key === 'engineering') {
+                const feeStandardItem = me.datas.find(d => d.key === 'feeStandard');
+                if (feeStandardItem && feeStandardItem.cellType === 'comboBox' && feeStandardItem.relatedOptions) {
+                    const relatedOptions = JSON.parse(feeStandardItem.relatedOptions);
+                    const options = relatedOptions[v];
+                    const feeStandardRow = me.datas.indexOf(feeStandardItem);
+                    me.setCombo(args.sheet, feeStandardRow, options);
+                    args.sheet.setValue(feeStandardRow, args.col, options[0]);
+                    feeStandardItem.value = options[0];
+                }
+            }
             me.datas[args.row].value = v;
         }
     },
@@ -197,6 +221,13 @@ let projFeatureView = {
         if(items.length === 0){
             return;
         }
+        let relatedOptions;
+        const feeStandardItem = me.datas.find(d => d.key === 'feeStandard');
+        if (feeStandardItem && feeStandardItem.cellType === 'comboBox' && feeStandardItem.relatedOptions) {
+            relatedOptions = JSON.parse(feeStandardItem.relatedOptions);
+        }
+        const engineeringItem = me.datas.find(d => d.key === 'engineering');
+        let engineeringVal = engineeringItem && engineeringItem.value || '';
         for(let i = 0, len = items.length; i < len; i++){
             let row = i + args.cellRange.row;
             let comboItems = me.getComboItemsByRow(row);
@@ -207,6 +238,27 @@ let projFeatureView = {
             else if (required && !items[i].value) {
                 recRows.push(row);
             }
+            // 特殊处理养护类别和费用标准
+            else if (me.datas[row].key === 'engineering') {
+                if (comboItems && !comboItems.includes(items[i].value)) {
+                    recRows.push(row);
+                } else {
+                    engineeringVal = items[i].value;
+                    if (relatedOptions) {
+                        const options = relatedOptions[items[i].value];
+                        const feeStandardRow = me.datas.indexOf(feeStandardItem);
+                        me.setCombo(args.sheet, feeStandardRow, options);
+                        args.sheet.setValue(feeStandardRow, args.cellRange.col, options[0]);
+                        feeStandardItem.value = options[0];
+                    }
+                }
+            }
+            else if (me.datas[row].key === 'feeStandard') {
+                const options = relatedOptions[engineeringVal];
+                if (!options.includes(items[i].value)) {
+                    args.sheet.setValue(row, args.cellRange.col, options[0]);
+                }
+            }
             //粘贴下拉框数据过滤
             else if(comboItems && !comboItems.includes(items[i].value)){
                 recRows.push(row);

+ 35 - 15
web/building_saas/main/js/views/project_view.js

@@ -195,7 +195,7 @@ var projectObj = {
         }
         if (value!=undefined||value!=null) {
             if (colSetting.data.decimal) {
-                value = value.toDecimal(colSetting.data.decimal);   
+                value = value.toDecimal(colSetting.data.decimal);
             }
         } else if (editingText && editingText !== '') {
             value = null;
@@ -523,8 +523,10 @@ var projectObj = {
                 };
 
                 //计算基数赋值要经过解析和标准化,已在calculate里赋值
-                if(fieldName !== 'calcBase')
-                    calcTools.setFieldValue(node, fieldName, value);
+                if(fieldName !== 'calcBase'){
+                  calcTools.setFieldValue(node, fieldName, value);
+                  projectObj.mainController.refreshTreeNode([node]);  // 量价,输入单价x,反算单价x1,第二次输入单价x,单价不再反算。(实际反算了,没刷新)
+                }
 
                 project.calcProgram.calcAndSave(node);
                 gljOprObj.showRationGLJSheetData();
@@ -557,6 +559,9 @@ var projectObj = {
         let colSetting = projectObj.mainController.setting.cols[info.col];
         projectObj.lastCol = colSetting;
         projectObj.lastCell = {row: info.row, col: info.col};
+        if(colSetting.data.field === 'quantity'){
+            SheetDataHelper.hideMoreButton()
+        }
     },
     //repaint 动态下拉框
     mainSpreadEnterCell: function (sender, info) {
@@ -573,6 +578,13 @@ var projectObj = {
             }
         }
     },
+      //滚动造价书鼠标时,工程量的更多按钮跟着移动
+    TopRowChanged:function(type,info){
+        let colSetting = projectObj.mainController.setting.cols[info.sheet.getActiveColumnIndex()];
+        if(colSetting.data.field === 'quantity'){
+            SheetDataHelper.moveMoreButton(info.sheet)
+        }
+    },
     mainSpreadEditStarting: function (sender, info) {
         let project = projectObj.project;
         let node = project.mainTree.items[info.row];
@@ -624,7 +636,7 @@ var projectObj = {
             }
         }
         if(node.sourceType == ModuleNames.ration){ //在定额编码中双击,如果右侧定额库没有展开,则自动展开。
-          if(node.data.type != rationType.ration) return ;//只有定额类型才需要自动展开,其它都不用 
+          if(node.data.type != rationType.ration) return ;//只有定额类型才需要自动展开,其它都不用
             let libID = node.data.libID;
             if (node.data.from === 'cpt') {
                 libID = node.data.fromUser ? `${rationLibObj.compleRationLibId}*${node.data.fromUser}` : rationLibObj.compleRationLibId;
@@ -952,15 +964,13 @@ var projectObj = {
                     // }
 
                 });
-                let startShowTime = +new Date();
                 that.mainController = TREE_SHEET_CONTROLLER.createNew(that.project.mainTree, that.mainSpread.getActiveSheet(), that.project.projSetting.mainGridSetting);
-                that.mainController.showTreeData();
-                let endShowTime = +new Date();
                 that.mainController.bind('refreshBaseActn', that.refreshBaseActn);
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.beforeTreeSelectedChange, that.beforeMainTreeSelectedChange);
                 that.mainController.bind(TREE_SHEET_CONTROLLER.eventName.treeSelectedChanged, that.treeSelectedChanged);
                 gljCol.initGljCol(that.project.projSetting.glj_col?that.project.projSetting.glj_col.showAdjustPrice:false,
-                that.project.property.tenderSetting.showTenderFields?that.project.property.tenderSetting.showTenderFields:false);
+                that.project.property.tenderSetting.showTenderFields?that.project.property.tenderSetting.showTenderFields:false,true);
+                that.mainController.showTreeData();
                 subObj.initSubSpread();//初始化主界面下方的表格
                 if(!projectReadOnly){
                     that.mainSpreadEscKey(that.mainSpread, that.mainSpreadEditStarting, that.mainSpreadEditEnded);
@@ -983,6 +993,10 @@ var projectObj = {
                 that.mainSpread.bind(GC.Spread.Sheets.Events.CellDoubleClick, that.onCellDoubleClick);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.ColumnWidthChanged, that.onColumnWidthChanged);
                 that.mainSpread.bind(GC.Spread.Sheets.Events.ClipboardPasting, that.onClipboardPasting);
+
+
+                //工程量悬浮窗移动事件
+                that.mainSpread.bind(GC.Spread.Sheets.Events.TopRowChanged, that.TopRowChanged);
                 //let loadOtherStartTime = +new Date();
                 //if(!projectReadOnly){
                     that.loadMainSpreadContextMenu();
@@ -1166,15 +1180,15 @@ var projectObj = {
 
     },
     isInsertEquipmentVisable:function(selected){
-      //浙江不管是预算或者工程量清单,都是隐藏,overwrite文件重写   
+      //浙江不管是预算或者工程量清单,都是隐藏,overwrite文件重写
       if(this.project.property.valuationType !=='ration' ){//属于预算项目的情况下,在固定清单可见
         //属于的固定清单
         let belongFlag = cbTools.getBelongFlag(selected);
         if (belongFlag && belongFlag === fixedFlag.EQUIPMENT_ACQUISITION_FEE) {
             return true;
         }
-        return false; 
-      } 
+        return false;
+      }
       return true
     },
     // 注册自定义插入清单数量
@@ -1621,7 +1635,11 @@ var projectObj = {
                     name: '造价计算',
                     icon: 'fa-calculator',
                     callback: function () {
-                        project.calcProgram.calcAllNodesAndSave();
+                        $.bootstrapLoading.start();
+                        setTimeout(function(){
+                            project.calcProgram.calcAllNodesAndSave();
+                            $.bootstrapLoading.end();
+                        },100)
                     },
                     disabled: function () {
                         if (projectReadOnly) {
@@ -1829,10 +1847,12 @@ var projectObj = {
         let max = 0;
         let total = 0;
         let counter = 0;
+        let notNumber = false; //如果有非数字,则不显示
         for (let col = selectedArea.col; col < (selectedArea.colCount + selectedArea.col); col++) {
             for (let row = selectedArea.row; row < (selectedArea.rowCount + selectedArea.row); row++) {
                 const value = sheet.getCell(row, col).text();
                 if (!regular.test(value)) {
+                    if(value) notNumber = true;
                     continue;
                 }
                 counter++;
@@ -1845,7 +1865,7 @@ var projectObj = {
             }
         }
         // 如果不为0则悬浮显示
-        if (total > 0 && counter > 1) {
+        if (notNumber === false && total > 0 && counter > 1) {
             const div = $('<div id="total-tips"><p>合计: <input type="text" id="total" readonly="readonly" style="border: none;"/></p><p><a href="javascript:void(0);">复制</a></p></div>');
             div.css({
                 position: "absolute",
@@ -2444,7 +2464,7 @@ $('#poj-set').on('show.bs.modal', function () {
         setCalcFlag($('#billsPrice'), leafBillGetFeeType.billsPrice, ft);
         setCalcFlag($('#zangu_common'), zanguCalcType.common, zg);
         setCalcFlag($('#zangu_gatherMaterial'), zanguCalcType.gatherMaterial, zg);
-        
+
         let showAdjustPrice = projectObj.project.projSetting.glj_col?projectObj.project.projSetting.glj_col.showAdjustPrice:false;
         showAdjustPrice === true ? $("#tab_poj-settings-6").show():$("#tab_poj-settings-6").hide();
         projDisplayView.init();
@@ -3532,4 +3552,4 @@ $('.limit-price-input').bind('input', function () {
         alert(err);
         $(this).val(orgVal);
     }
-});
+});

+ 24 - 11
web/building_saas/main/js/views/quantity_edit_view.js

@@ -62,9 +62,10 @@ let quantityEditObj = {
         }
         QuantityEditCellType.prototype = new ns.CellTypes.Text();
         QuantityEditCellType.prototype.paint = function (ctx, value, x, y, w, h, style, options) {
+            let me=quantityEditObj;
             if(!projectReadOnly){
                 if(options.sheet.getActiveRowIndex()==options.row&&options.sheet.getActiveColumnIndex()==options.col){
-                    var image = document.getElementById('f_btn'),imageMagin = 3;
+                  /*   var image = document.getElementById('f_btn'),imageMagin = 3;
                     var imageHeight = 15;
                     var imageWidth = 25;
                     var imageX = x + w - imageWidth- imageMagin, imageY = y + h / 2 - imageHeight / 2;
@@ -80,12 +81,18 @@ let quantityEditObj = {
                     ctx.fill();//画实心圆
                     ctx.closePath();
                     ctx.restore();
-                    w = w - imageWidth - imageMagin;
+                    w = w - imageWidth - imageMagin; */
+                    if(options.sheet.getCell(options.row,options.col).locked() != true){
+                        SheetDataHelper.showMoreButton({sheet:options.sheet,cellRect:{x,y,width: w,height:h},row:options.row },function(row){
+                            me.showSelectModal(row);
+                        })
+                     }
+
                 }
             }
             GC.Spread.Sheets.CellTypes.Text.prototype.paint.apply(this, arguments);
         };
-        QuantityEditCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
+      /*   QuantityEditCellType.prototype.getHitInfo = function (x, y, cellStyle, cellRect, context) {
             return {
                 x: x,
                 y: y,
@@ -96,9 +103,10 @@ let quantityEditObj = {
                 sheetArea: context.sheetArea
             };
         };
-
+ */
         //2018 -09 -26  修改工程量这个输入控件,删除悬浮提示注释,还原时通过git 历史
-        QuantityEditCellType.prototype.processMouseDown = function (hitinfo) {
+        //2021 -04 -16  悬浮提示到表格外面
+      /*   QuantityEditCellType.prototype.processMouseDown = function (hitinfo) {
             let me=quantityEditObj;
             if(hitinfo.sheet.getActiveRowIndex()==hitinfo.row&&hitinfo.sheet.getActiveColumnIndex()==hitinfo.col){
                 var offset=hitinfo.cellRect.x+hitinfo.cellRect.width-6;
@@ -109,21 +117,21 @@ let quantityEditObj = {
                     }
                 }
             }
-        };
+        }; */
         return new QuantityEditCellType();
     },
-    showSelectModal:function (hitinfo) {
+    showSelectModal:function (row) {
         //锁定的清单不显示
         let project = projectObj.project;
         if(project.mainTree.selected.sourceType == ModuleNames.bills && project.isBillsLocked() && project.withinBillsLocked(project.mainTree.selected)){
             return;
         }
-        this.initModalContent(hitinfo);
+        this.initModalContent(row);
         $("#quantityEXPEdit").modal({show:true});
     },
-    initModalContent:function (hitinfo) {
+    initModalContent:function (row) {
         //现在改成有可能点击时,还没选中节点,所以要靠row来判断
-        let selected = projectObj.project.mainTree.items[hitinfo.row];
+        let selected = projectObj.project.mainTree.items[row];
         if(selected.sourceType == ModuleNames.ration){//暂时只有定额才有基数选择,所以其它的先隐藏表格
             $("#quantityEditSpread").show();//quantityEditSpread
         }else {
@@ -141,8 +149,10 @@ let quantityEditObj = {
             return true;
         }*/
         quantityEXP = quantityEXP?quantityEXP.toUpperCase():'';//非空判断
-        quantityEXP =replaceAll('(','(',quantityEXP);//转换中文左右符号
+        quantityEXP =replaceAll('(','(',quantityEXP);//转换中文左右符号与。、
         quantityEXP =replaceAll(')',')',quantityEXP);
+        quantityEXP =replaceAll('。','.',quantityEXP);
+        quantityEXP =replaceAll('、','/',quantityEXP);
         quantityEXP = quantityEXP.replace(/[\s\r\n]/g, "")//去掉空格回车换行等字符
         let value = me.evalQuantityExp(quantityEXP,node);
         if(value!=='evalError'){
@@ -164,6 +174,8 @@ let quantityEditObj = {
     },
     evalQuantityExp(quantityEXP,node){
         let evalString = quantityEXP;
+        //求余% 换成 * 0.01 再计算
+         evalString =handlePercent(evalString);
         if( node.sourceType == ModuleNames.ration && quantityEXP.indexOf('QDL')!=-1){
             let billNode = node.parent;
             let bQuantity = 0;
@@ -182,6 +194,7 @@ let quantityEditObj = {
                 let exp = new Expression('');
                 exp.Expression(evalString);
                 value = Number(exp.Evaluate());
+                if(isNaN(value)) throw new Error("输入的表达式有误");
             }
             return value;
         }catch (error){

+ 8 - 8
web/building_saas/main/js/views/tender_price_view.js

@@ -60,12 +60,12 @@ let tender_obj={
                 newNode.sourceType = mainNode.sourceType;
                 newNode.mainNode = mainNode;
 
-                // 只显示到叶子清单层
-                if (calcTools.isLeafBill(newNode))
-                    newNode.expanded = false;
-
-                if (calcTools.isRationCategory(newNode))
-                    newNode.visible = false;
+                // 只显示到叶子清单层AAAAAA
+                // if (calcTools.isLeafBill(newNode))
+                //     newNode.expanded = false;
+                //
+                // if (calcTools.isRationCategory(newNode))
+                //     newNode.visible = false;
 
                 if (mainNode.children.length > 0) {
                     for (let c of mainNode.children) {
@@ -429,7 +429,7 @@ let tender_obj={
         let tenderSetting = projectObj.project.property.tenderSetting;
         let gljPriceTenderCoe = tenderSetting && tenderSetting.gljPriceTenderCoe?tenderSetting.gljPriceTenderCoe:1;
         let showTenderFields = tenderSetting && tenderSetting.showTenderFields?tenderSetting.showTenderFields:false;
-        let calcPriceOption = calcTools.getTenderCalcType();
+        let calcPriceOption = calcTools.getTenderTypeStr();
         $('#calcPriceOption').val(calcPriceOption);
         $('#gljPriceTenderCoe').val(gljPriceTenderCoe);
         $('#cbShowTenderFields').prop("checked", showTenderFields);
@@ -578,4 +578,4 @@ $(function () {
         gljCol.showTenderFields(showFields, true);
     });
 
-});
+});

+ 2 - 1
web/building_saas/pm/js/pm_newMain.js

@@ -1742,7 +1742,8 @@ const projTreeObj = {
 function changeValuationType(type) {
     $('input[name="valuation_type"]:checked').prop('checked', false);
     $(`input[name="valuation_type"][value="${type}"]`).prop('checked', true);
-    let targetData = type === 'bill' ? JSON.parse(billValuation) : JSON.parse(rationValuation);
+    // let targetData = type === 'bill' ? JSON.parse(billValuation) : JSON.parse(rationValuation);
+    let targetData = getValuationData(type);
     let html = '';
     for(let i = targetData.length - 1; i >=0; i--){
         let valuation = targetData[i];

+ 8 - 1
web/building_saas/standard_interface/config.js

@@ -17,7 +17,6 @@ const INTERFACE_CONFIG = (() => {
   return {
     '安徽@马鞍山': {
       scriptName: 'anhui_maanshan.js',
-      //feeRateStandard: '安徽估概预算-皖交建管函[2019]210号', 不需要导入费率了
       fileSuffix: {
         [BID_INVITATION]: '.MASGLZB',
         [BID_SUBMISSION]: '.MASGLTB',
@@ -87,6 +86,14 @@ const INTERFACE_CONFIG = (() => {
         [BID_SUBMISSION]: '.XML',
         [CONTROL]: '.XML',
       },
+    },
+    '新疆@新疆': {
+      scriptName: 'anhui_maanshan.js',
+      fileSuffix: {
+        [BID_INVITATION]: '.xjglzbx',
+        [BID_SUBMISSION]: '.xjgltbx',
+        [CONTROL]: '.xjglkzjx',
+      },
     }
   };
 })()

+ 16 - 6
web/building_saas/standard_interface/export/anhui_chizhou.js

@@ -428,6 +428,14 @@ INTERFACE_EXPORT = (() => {
         }
 
         function createZaoJHZB(Bid, ZaoJHZB) {
+            const flagToLB = {
+                [fixedFlag.ONE_SEVEN_BILLS]: '1',
+                [fixedFlag.PROVISIONAL_TOTAL]: '2',
+                [fixedFlag.BILLS_TOTAL_WT_PROV]: '3',
+                [fixedFlag.DAYWORK_LABOR]: '4',
+                [fixedFlag.PROVISIONAL]: '5',
+                [fixedFlag.TOTAL_COST]: '6',
+            };
             const map_ZC_LB = [
                 {reg: /(第?100章?至第?700章?)/, zc: '', lb: '1'},
                 {reg: /已包含在清单合计中的材料/, zc: '', lb: '2'},
@@ -444,10 +452,13 @@ INTERFACE_EXPORT = (() => {
                 {reg: /第700章/, zc: '700', lb: '17'}
             ]
 
-            function getZCLB(name, kind){
-                let rst = '';
+            function getZCLB(flag, name, kind){
+                let rst = kind === 2 ? flagToLB[flag] || '' : '';
+                if (rst) {
+                    return rst;
+                }
+                const trimName = (name || '').replace(/\s/g, '');
                 for (let i = 0; i < map_ZC_LB.length; i++){
-                    const trimName = (name || '').replace(/\s/g, '');
                     if (map_ZC_LB[i].reg.test(trimName)){
                         if (kind == 1)
                             rst = map_ZC_LB[i].zc
@@ -465,7 +476,6 @@ INTERFACE_EXPORT = (() => {
                 else
                     return (node.data.feesIndex && node.data.feesIndex.common ? node.data.feesIndex.common.tenderTotalFee : 0);
             }
-            debugger;
             let nodes = [vTree.roots[0], ...vTree.roots[0].children, ...vTree.roots.slice(1)];
 
             let hzmxNo = 0;
@@ -474,10 +484,10 @@ INTERFACE_EXPORT = (() => {
                 hzmxNo++;
                 let attrs = [
                     { name: '序号', value: hzmxNo },
-                    { name: '章次', value: getZCLB(node.data.name, 1) },
+                    { name: '章次', value: getZCLB(node.getFlag(), node.data.name, 1) },
                     { name: '名称', value: node.data.name },
                     { name: '金额', value: getJE(node) },
-                    { name: '类别', value: getZCLB(node.data.name, 2) },
+                    { name: '类别', value: getZCLB(node.getFlag(), node.data.name, 2) },
                     { name: '备注', value: node.data.remark }
                 ];
                 const zaoJHZMX = new CreateNode('造价汇总明细', attrs);

+ 35 - 26
web/building_saas/standard_interface/export/anhui_maanshan.js

@@ -26,6 +26,7 @@ INTERFACE_EXPORT = (() => {
         getValueByKey,
         getHan,
         getFee,
+        getUnitFee,
         generateHardwareId,
       },
       Element,
@@ -389,15 +390,15 @@ INTERFACE_EXPORT = (() => {
         { name: 'Dw', value: node.data.unit }, // 单位
         { name: 'Sl', value: node.data.quantity, type: TYPE.DECIMAL }, // 工程量
         { name: 'Sl2', value: '0', type: TYPE.DECIMAL }, // 工程量2
-        { name: 'Rgf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'marketLabour.tenderTotalFee'), type: TYPE.DECIMAL }, // 人工费
-        { name: 'Clf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'marketMaterial.tenderTotalFee'), type: TYPE.DECIMAL }, // 材料费
-        { name: 'Jxf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'marketMachine.tenderTotalFee'), type: TYPE.DECIMAL }, // 机械费
-        { name: 'Sbf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'marketEquipment.tenderTotalFee'), type: TYPE.DECIMAL }, // 设备费
-        { name: 'Csf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'measure.tenderTotalFee'), type: TYPE.DECIMAL }, // 措施费
-        { name: 'Glf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'manage.tenderTotalFee'), type: TYPE.DECIMAL }, // 企业管理费
-        { name: 'Gf', value: isBidInvitation ? '0' : getFee(node.data.fees, 'force.tenderTotalFee'), type: TYPE.DECIMAL }, // 规费
-        { name: 'Lr', value: isBidInvitation ? '0' : getFee(node.data.fees, 'profit.tenderTotalFee'), type: TYPE.DECIMAL }, // 利润
-        { name: 'Sj', value: isBidInvitation ? '0' : getFee(node.data.fees, 'tax.tenderTotalFee'), type: TYPE.DECIMAL }, // 税金
+        { name: 'Rgf', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'marketLabour.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 人工费
+        { name: 'Clf', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'marketMaterial.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 材料费
+        { name: 'Jxf', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'marketMachine.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 机械费
+        { name: 'Sbf', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'marketEquipment.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 设备费
+        { name: 'Csf', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'measure.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 措施费
+        { name: 'Glf', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'manage.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 企业管理费
+        { name: 'Gf', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'force.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 规费
+        { name: 'Lr', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'profit.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 利润
+        { name: 'Sj', value: isBidInvitation ? '0' : getUnitFee(getFee(node.data.fees, 'tax.tenderTotalFee'),node.data.quantity,2), type: TYPE.DECIMAL }, // 税金
         { name: 'Zhdj', value: isBidInvitation ? '0' : getFee(node.data.fees, 'common.tenderUnitFee'), type: TYPE.DECIMAL }, // 单价
         { name: 'Zhhj', value: isBidInvitation ? '0' : orgFee, type: TYPE.DECIMAL }, // 合价
         { name: 'Zgj', value: isBidInvitation ? '0' : getFee(node.data.fees, 'estimate.tenderTotalFee'), type: TYPE.DECIMAL }, // 暂估价
@@ -433,15 +434,15 @@ INTERFACE_EXPORT = (() => {
         { name: 'Sl', value: ration.tenderQuantity, type: TYPE.DECIMAL }, // 工程量
         { name: 'Dj', value: getFee(ration.fees, 'common.tenderUnitFee'), type: TYPE.DECIMAL }, // 单价
         { name: 'Hj', value: getFee(ration.fees, 'common.tenderTotalFee'), type: TYPE.DECIMAL }, // 合价
-        { name: 'Rgf', value: getFee(ration.fees, 'marketLabour.tenderTotalFee'), type: TYPE.DECIMAL }, // 人工费
-        { name: 'Clf', value: getFee(ration.fees, 'marketMaterial.tenderTotalFee'), type: TYPE.DECIMAL }, // 材料费
-        { name: 'Jxf', value: getFee(ration.fees, 'marketMachine.tenderTotalFee'), type: TYPE.DECIMAL }, // 机械费
-        { name: 'Sbf', value: getFee(ration.fees, 'marketEquipment.tenderTotalFee'), type: TYPE.DECIMAL }, // 设备费
-        { name: 'Csf', value: getFee(ration.fees, 'measure.tenderTotalFee'), type: TYPE.DECIMAL }, // 措施费
-        { name: 'Glf', value: getFee(ration.fees, 'manage.tenderTotalFee'), type: TYPE.DECIMAL }, // 企业管理费
-        { name: 'Gf', value: getFee(ration.fees, 'force.tenderTotalFee'), type: TYPE.DECIMAL }, // 规费
-        { name: 'Lr', value: getFee(ration.fees, 'profit.tenderTotalFee'), type: TYPE.DECIMAL }, // 利润
-        { name: 'Sj', value: getFee(ration.fees, 'tax.tenderTotalFee'), type: TYPE.DECIMAL }, // 税金
+        { name: 'Rgf', value: getUnitFee(getFee(ration.fees, 'marketLabour.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 人工费
+        { name: 'Clf', value: getUnitFee(getFee(ration.fees, 'marketMaterial.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 材料费
+        { name: 'Jxf', value: getUnitFee(getFee(ration.fees, 'marketMachine.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 机械费
+        { name: 'Sbf', value: getUnitFee(getFee(ration.fees, 'marketEquipment.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 设备费
+        { name: 'Csf', value: getUnitFee(getFee(ration.fees, 'measure.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 措施费
+        { name: 'Glf', value: getUnitFee(getFee(ration.fees, 'manage.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 企业管理费
+        { name: 'Gf', value: getUnitFee(getFee(ration.fees, 'force.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 规费
+        { name: 'Lr', value: getUnitFee(getFee(ration.fees, 'profit.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 利润
+        { name: 'Sj', value: getUnitFee(getFee(ration.fees, 'tax.tenderTotalFee'),ration.tenderQuantity,2), type: TYPE.DECIMAL }, // 税金
         { name: 'Delb', value: type, type: TYPE.INT }, // 取定额/量价/设备的类别。(1=普通定额,2=人工,3=材料,4=机械,5=设备)
         { name: 'Iszd', value: 'false', type: TYPE.BOOL }, // 暂时,全部取fals
       ];
@@ -474,8 +475,8 @@ INTERFACE_EXPORT = (() => {
         { name: 'Rcjhl', value: item.contain, type: TYPE.DECIMAL }, // 含量:取叶子清单下所有的人材机的含量,=各定额下的人材机总消耗量之和,再除以清单工程量
         { name: 'Rcjhj', value: item.totalPrice, type: TYPE.DECIMAL }, // 合价:人材机含量*人材机预算价
         { name: 'Zgjbz', value: item.isEvaluate, type: TYPE.BOOL }, // 是否暂估,根据资源ID,读取工料机汇总界面对应的“是否暂估”
-        { name: 'Zcbz', value: subArea === '芜湖' ? 'true' : 'false', type: TYPE.BOOL }, // 主材标记,公路上无此概念,默认输出=fales
-        { name: 'Zyclbz', value: subArea === '芜湖' ? 'false' : item.isMainMaterial, type: TYPE.BOOL }, // 根据资源ID,读取工料机汇总界面对应的“主要材料”
+        { name: 'Zcbz', value: 'false', type: TYPE.BOOL }, // 主材标记,公路上无此概念,默认输出=fales
+        { name: 'Zyclbz', value:  item.isMainMaterial, type: TYPE.BOOL }, // 根据资源ID,读取工料机汇总界面对应的“主要材料”
       ]
       Element.call(this, 'QdxrcjhlMx', attrs);
     }
@@ -548,6 +549,7 @@ INTERFACE_EXPORT = (() => {
       if (!['1', '2', '3'].includes(rootType)) {
         rootType = '2';
       }
+      
       const attrs = [
         { name: 'RcjId', value: projectGLJIDToRcjID[glj.id] }, // 资源ID
         { name: 'RcjBm', value: glj.code }, // 编码
@@ -561,10 +563,11 @@ INTERFACE_EXPORT = (() => {
         { name: 'Gycs', value: '' }, // 厂商
         { name: 'Rcjlb', value: rootType, type: TYPE.INT }, // 人材机类型 1=人工;2=材料;3=机械
         { name: 'Jgbz', value: 'false', type: TYPE.BOOL }, // 供材方
-        { name: 'Zyclbz', value: subArea === '芜湖' ? 'false' : !!glj.is_main_material, type: TYPE.BOOL }, // 主要材料
+        { name: 'Zyclbz', value:  !!glj.is_main_material, type: TYPE.BOOL }, // 主要材料
         { name: 'Zgjbz', value: !!glj.is_evaluate, type: TYPE.BOOL }, // 是否暂估
-        { name: 'Zcbz', value: subArea === '芜湖' ? 'true' : 'false', type: TYPE.BOOL }, // 主材标记
+        { name: 'Zcbz', value: 'false' , type: TYPE.BOOL }, // 主材标记
       ];
+      console.log(!!glj.is_main_material);
       Element.call(this, 'RcjhzMx', attrs);
     }
 
@@ -718,7 +721,7 @@ INTERFACE_EXPORT = (() => {
           const subIsRations = node.children.length && !node.source.children.length;
           if (subIsRations) {
             qdmx.children.push(...setupRations(node.children));
-            qdmx.children.push(...setupBillsContain(node.data));
+            qdmx.children.push(...setupBillsContain(node.data,node.children));
           } else {
             qdmx.children.push(...setupSubBills(node.children, allNodes));
           }
@@ -740,6 +743,7 @@ INTERFACE_EXPORT = (() => {
 
       return qdxm;
     }
+    
 
     // 组装定额、定额人材机数据
     function setupRations(rationNodes) {
@@ -764,10 +768,14 @@ INTERFACE_EXPORT = (() => {
     }
 
     // 组装清单人材机含量数据
-    function setupBillsContain(bills) {
+    function setupBillsContain(bills,rationNodes) {
       if (isBidInvitation) {
         return [];
       }
+      const rationIDMap = {};
+      for(const node of rationNodes){
+        rationIDMap[node.data.ID] = node.data;
+      }
       // 读取清单下的人材机,先将各定额下的人材机汇总,相同的合并(相同的项目人材机ID)
       const gljList = curDetail.ration_glj.datas.filter(glj => glj.billsItemID === bills.ID);
       if (!gljList) {
@@ -779,13 +787,14 @@ INTERFACE_EXPORT = (() => {
           const projectGLJ = projectGLJMap[glj.projectGLJID];
           map[glj.projectGLJID] = {
             rcjID: projectGLJIDToRcjID[glj.projectGLJID],
-            totalQuantity: glj.tenderQuantity,
+            totalQuantity: !!rationIDMap[glj.rationID]?gljOprObj.getTotalQuantity(glj,rationIDMap[glj.rationID]):0 ,
             price: projectGLJ.priceInfo.tenderPrice,
             isEvaluate: !!projectGLJ.is_evaluate,
             isMainMaterial: !!projectGLJ.is_main_material
           };
         } else {
-          map[glj.projectGLJID].totalQuantity = scMathUtil.roundTo(map[glj.projectGLJID].totalQuantity + glj.tenderQuantity, -6);
+          const subQuantity = !!rationIDMap[glj.rationID]?gljOprObj.getTotalQuantity(glj,rationIDMap[glj.rationID]):0;
+          map[glj.projectGLJID].totalQuantity = scMathUtil.roundTo(map[glj.projectGLJID].totalQuantity + subQuantity, -6);
         }
       });
       const containItems = Object

+ 10 - 0
web/building_saas/standard_interface/export/base.js

@@ -252,6 +252,15 @@ const INTERFACE_EXPORT_BASE = (() => {
     }
     return fee[fields[1]] || 0;
   }
+
+  //取单价等
+  function getUnitFee(fee,quantity,decimal){
+    if(!!quantity && quantity!==0){
+      return scMathUtil.roundForObj(fee/parseFloat(quantity),decimal)
+    }
+    return fee
+  }
+
   // 获取节点的汇总价格
   function getAggregateFee(nodes) {
     const total = nodes.reduce((acc, node) => {
@@ -687,6 +696,7 @@ const INTERFACE_EXPORT_BASE = (() => {
     hasValue,
     setTimeoutSync,
     getFee,
+    getUnitFee,
     getAggregateFee,
     getFeeByFlag,
     getPlainAttrs,

+ 3 - 2
web/building_saas/standard_interface/import/anhui_chizhou.js

@@ -83,13 +83,14 @@ INTERFACE_IMPORT = (() => {
         .filter(item => !getValue(item, ['_章次']))
         .map(item => ({
           name: getValue(item, ['_名称']),
-          remark: getValue(item, ['_备注'])
+          remark: getValue(item, ['_备注']),
+          titleType: getValue(item, ['_类别'])
         }));
       let oneSevenBills;
       let dayWorkBills;
       roots.forEach(item => {
         const simpleName = item.name ? item.name.replace(/\s/g, '') : '';
-        if (/100章至第700章|100章至700章/.test(simpleName)) {
+        if (item.titleType === '1' || /100章至第700章|100章至700章/.test(simpleName)) {
           oneSevenBills = item;
         } else if (/计日工合计/.test(simpleName)) {
           dayWorkBills = item;

+ 3 - 1
web/building_saas/standard_interface/import/anhui_maanshan.js

@@ -184,7 +184,9 @@ INTERFACE_IMPORT = (() => {
         if (curField === qdbt) {
           item.code = getValue(src, ['_Bm']);
           item.rowCode = getValue(src, ['_Code']); // 注意:行号标记,用于后续(通用处理)清单基数进行转换(行引用转换为ID引用) 
-          if (getValue(src, ['_Lb']) === '5') { // 暂列金额才导入计算基数
+          const titleType = getValue(src, ['_Lb']);
+          item.titleType = titleType;
+          if (titleType === '5') { // 暂列金额才导入计算基数
             item.calcBase = getValue(src, ['_Jsgs']);
           }
         } else if (curField === qdmx) {

+ 27 - 7
web/building_saas/standard_interface/import/base.js

@@ -228,6 +228,16 @@ const INTERFACE_EXPORT_BASE = (() => {
 
   const { fixedFlag, BillType } = window.commonConstants;
 
+  // 标题类别 - flag 映射
+  const titleTypeToFlag = {
+    1: fixedFlag.ONE_SEVEN_BILLS,
+    2: fixedFlag.PROVISIONAL_TOTAL,
+    3: fixedFlag.BILLS_TOTAL_WT_PROV,
+    4: fixedFlag.DAYWORK_LABOR,
+    5: fixedFlag.PROVISIONAL,
+    6: fixedFlag.TOTAL_COST,
+  }
+
   /**
    * 将提取出来的清单合并进清单模板
    * @param {Array} source - 从xml提取出来的清单
@@ -236,21 +246,26 @@ const INTERFACE_EXPORT_BASE = (() => {
    * @return {void}
    */
   function mergeBills(source, target, parent) {
-    source.forEach(bills => {
+    source.forEach((bills, index) => {
+      // 为了大项费用排序
+      if (!parent) {
+        bills.seq = index;
+      }
       const simpleName = bills.name ? bills.name.replace(/\s/g, '') : '';
+      const titleType = bills.titleType || '0';
       let matched;
       if (!parent) {
-        if (/100章.*700章|100章.*900章/.test(simpleName)) {
+        if (titleTypeToFlag[titleType] === fixedFlag.ONE_SEVEN_BILLS || /100章.*700章|100章.*900章/.test(simpleName)) {
           matched = target.find(bills => getFlag(bills) === fixedFlag.ONE_SEVEN_BILLS);
-        } else if (/包含在清单合计中的材料、工程设备、专业工程暂估/.test(simpleName)) {
+        } else if (titleTypeToFlag[titleType] === fixedFlag.PROVISIONAL_TOTAL || /包含在清单合计中的材料、工程设备、专业工程暂估/.test(simpleName)) {
           matched = target.find(bills => getFlag(bills) === fixedFlag.PROVISIONAL_TOTAL);
-        } else if (/清单合计减去材料、工程设备、专业工程暂估价/.test(simpleName)) {
+        } else if (titleTypeToFlag[titleType] === fixedFlag.BILLS_TOTAL_WT_PROV || /清单合计减去材料、工程设备、专业工程暂估价/.test(simpleName)) {
           matched = target.find(bills => getFlag(bills) === fixedFlag.BILLS_TOTAL_WT_PROV);
-        } else if (/计日工合计/.test(simpleName)) {
+        } else if (titleTypeToFlag[titleType] === fixedFlag.DAYWORK_LABOR || /计日工合计/.test(simpleName)) {
           matched = target.find(bills => getFlag(bills) === fixedFlag.DAYWORK_LABOR);
-        } else if (/暂列金额[((]不含/.test(simpleName)) {
+        } else if (titleTypeToFlag[titleType] === fixedFlag.PROVISIONAL || /暂列金额[((]不含/.test(simpleName)) {
           matched = target.find(bills => getFlag(bills) === fixedFlag.PROVISIONAL);
-        } else if (/报价/.test(simpleName)) {
+        } else if (titleTypeToFlag[titleType] === fixedFlag.TOTAL_COST || /报价/.test(simpleName)) {
           matched = target.find(bills => getFlag(bills) === fixedFlag.TOTAL_COST);
         }
       } else {
@@ -288,6 +303,8 @@ const INTERFACE_EXPORT_BASE = (() => {
     const rst = [];
     // 将提取的清单数据合并进清单模板数据
     mergeBills(tenderBills, billsTarget, null);
+    // 大项费用按照清单标题排序
+    billsTarget.sort((a, b) => a.seq - b.seq);
     // 给清单设置数据
     const rowCodeData = []; // 行号数据,用于转换行引用
     const toBeTransformBills = []; // 待转换的清单
@@ -299,6 +316,9 @@ const INTERFACE_EXPORT_BASE = (() => {
         if (!child.ID) {
           child.ID = uuid.v1();
         }
+        if (child.quantity) {
+          child.quantityEXP = child.quantity;
+        }
         child.ParentID = parentID;
         child.type = parentID === -1 ? BillType.DXFY : BillType.BILL;
         child.NextSiblingID = -1;

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

@@ -49,6 +49,8 @@
                     <img width="38" src="/web/building_saas/img/vip2.png" data-toggle="tooltip" data-placement="bottom" data-original-title="借用">
                     <% } else if (sessionUser.compilationLock === 2) { %>
                     <img width="38" src="/web/building_saas/img/vip.png" data-toggle="tooltip" data-placement="bottom" data-original-title="购买">
+                    <% } else if (sessionUser.compilationLock === 3) { %>
+                    <img width="38" src="/web/building_saas/img/vip3.png" data-toggle="tooltip" data-placement="bottom" data-original-title="赠送">
                     <% } %>
                 </a>
             </li>

BIN
web/dest/css/img/more.png


+ 75 - 0
web/over_write/js/gansu_2017

@@ -0,0 +1,75 @@
+/**
+ * Created by CSL on 2021/04/25.  甘肃养护计算程序、基数 等覆盖。
+ */
+
+let isGS2017 = true;
+function overwriteRationCalcBases() {
+  if (typeof rationCalcBases == 'undefined') return;
+  for (let key in rationCalcBases) delete rationCalcBases[key];
+
+  rationCalcBases['人工费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, [gljType.LABOUR], priceTypes.ptMarketPrice, isTender);
+  };
+  rationCalcBases['材料费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, baseMaterialTypes, priceTypes.ptMarketPrice, isTender);
+  };
+  rationCalcBases['施工机械使用费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, baseMachineTypes, priceTypes.ptMarketPrice, isTender);
+  };
+  rationCalcBases['施工机械人工费'] = function (node, isTender) {
+    return calcTools.machineDetailFee(node, node.data.gljList, [], gljType.MACHINE_LABOUR, isTender);
+  };
+  rationCalcBases['设备购置费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, [gljType.EQUIPMENT], priceTypes.ptMarketPrice, isTender);
+  };
+
+  rationCalcBases['定额人工费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, [gljType.LABOUR], priceTypes.ptBasePrice, isTender);
+  };
+  rationCalcBases['定额材料费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, baseMaterialTypes, priceTypes.ptBasePrice, isTender);
+  };
+  rationCalcBases['定额施工机械使用费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, baseMachineTypes, priceTypes.ptBasePrice, isTender);
+  };
+  rationCalcBases['定额商品砼费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, [gljType.COMMERCIAL_CONCRETE, gljType.COMMERCIAL_MORTAR], priceTypes.ptBasePrice, isTender);
+  };
+  rationCalcBases['定额设备费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, [gljType.EQUIPMENT], priceTypes.ptBasePrice, isTender);
+  };
+  rationCalcBases['定额外购砼构件费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, [gljType.PURCHASE_COMPONENT], priceTypes.ptBasePrice, isTender);
+  };
+  rationCalcBases['定额绿化苗木费'] = function (node, isTender) {
+    return calcTools.rationBaseFee(node, [gljType.GREEN_SEEDLING], priceTypes.ptBasePrice, isTender);
+  };
+};
+
+(function overwriteFeeTypes() {
+  if (typeof cpFeeTypes == 'undefined') return;
+  cpFeeTypes = [
+    { type: 'marketLabour', name: '人工费' },
+    { type: 'marketMaterial', name: '材料费' },
+    { type: 'marketMachine', name: '施工机械使用费' },
+    { type: 'marketMachineLabour', name: '施工机械人工费' },
+    { type: 'marketEquipment', name: '设备购置费' },
+    { type: 'marketDirect', name: '直接费' },
+
+    { type: 'labour', name: '定额人工费' },
+    { type: 'material', name: '定额材料费' },
+    { type: 'machine', name: '定额施工机械使用费' },
+    { type: 'equipment', name: '定额设备费' },
+    { type: 'direct', name: '定额直接费' },
+
+    { type: 'measure', name: '措施费' },
+    { type: 'measure1', name: '措施费I' },
+    { type: 'measure2', name: '措施费II' },
+    { type: 'manage', name: '企业管理费' },
+    { type: 'force', name: '规费' },
+    { type: 'profit', name: '利润' },
+    { type: 'tax', name: '税金' },
+    { type: 'common', name: '建安费' },
+    { type: 'rationCommon', name: '定额建安费' }
+  ];
+})();

+ 14 - 0
web/over_write/js/gansu_2017.js

@@ -0,0 +1,14 @@
+if (typeof feeRateObject !== 'undefined') {
+    feeRateObject.feeRateSpecialHandle = function (subRate, value) {
+        let result = {};
+        if (subRate.name == "工地转移(km)" && value && value < 50) {//工地转移50km以内按50km算
+            result.valueKey = "50";
+            result.value = scMathUtil.roundForObj(value, getDecimal("feeRate"));//设置显示的节点值
+        }
+        if (subRate.name == "施工进出场(km)" && value && value < 5) {//施工进出场5km以内按5km算
+            result.valueKey = "5";
+            result.value = scMathUtil.roundForObj(value, getDecimal("feeRate"));//设置显示的节点值
+        }
+        return result;
+    }
+}

+ 59 - 61
web/over_write/js/quanguo_2018.js

@@ -172,8 +172,15 @@ if (typeof baseFigureMap !== 'undefined') {
     '定额建筑安装工程费': {
       base: 'DEJZAZGCF',
       fixedFlag: fixedFlag.CONSTRUCTION_INSTALL_FEE,
-      filter: [fixedFlag.CONSTRUCTION_INSTALL_FEE],
-      pick: false
+      filter: [/* fixedFlag.CONSTRUCTION_INSTALL_FEE */],
+      pick: true
+    },
+    // 显示:仅清单固定类别是“安全生产费”行可显示
+    '建筑安装工程费(不含安全生产费)': {
+      base: 'JZAZGCFBHSC',
+      fixedFlag: null, // 防止触发循环计算
+      filter: [fixedFlag.SAFE_COST],
+      pick: true
     },
     // 显示:仅清单固定类别是“工程建设其他费”部分可显示
     '建筑安装工程费(不含设备费)': {
@@ -189,11 +196,11 @@ if (typeof baseFigureMap !== 'undefined') {
       filter: [fixedFlag.MAINTENANCE_EXPENSES],
       pick: true
     },
-    // 显示:仅清单固定类别是“工程建设其他费”、“专项费用”部分可显示
+    // 显示:仅清单固定类别是“工程建设其他费”可显示
     '定额建筑安装工程费(不含定额设备购置费、专项费用)': {
       base: 'DEJZAZGCFBHSBZX',
       fixedFlag: null,
-      filter: [fixedFlag.MAINTENANCE_EXPENSES, fixedFlag.SPECIAL_COST],
+      filter: [/* fixedFlag.MAINTENANCE_EXPENSES */],
       pick: true,
     },
     // 显示:仅清单固定类别是“施工场地建设费”的可显示
@@ -296,116 +303,107 @@ if (typeof baseFigureTemplate !== 'undefined') {
     DEJZAZGCF(tender) {
       return cbTools.getBaseFee(fixedFlag.CONSTRUCTION_INSTALL_FEE, tender, 'rationCommon');
     },
-    // 建设安装工程费(不含设备费) 算法:取固定类别是“建筑安装工程费”的金额。扣除设备的金额。(全国造价云版中,没有固定的设备购置行,需要扣除所有类别是“设备”的金额,仅指设备行,不包括定额工料机的设备)
+    // 建筑安装工程费(不含安全生产费) 算法:取固定类别是“建筑安装工程费”的“建安费”,扣除固定类别是“安全生产费”的“建安费”
+    JZAZGCFBHSC(tender) {
+      let baseFee = this['JZAZGCF'](tender);
+      const safeFee = cbTools.getBaseFee(fixedFlag.SAFE_COST, tender, 'common');
+      return (baseFee - safeFee).toDecimal(decimalObj.bills.totalPrice);
+    },
+    // 建设安装工程费(不含设备费) 算法:取固定类别是“建筑安装工程费”的建安费。扣除设备的定额设备费。(全国造价云版中,没有固定的设备购置行,需要扣除所有类别是“设备”的金额,仅指设备行,不包括定额工料机的设备)
     JZAZGCFBHSB(tender) {
       let baseFee = this['JZAZGCF'](tender);
       const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
-      const allSubNodes = [];
-      projectObj.project.mainTree.getAllSubNode(fixedNode, allSubNodes);
-      const equipmentNodes = allSubNodes.filter(node => node.data.type === rationType.gljRation && node.data.subType === gljType.EQUIPMENT);
-      const feeField = 'common';
-      const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
-      let totalEquipmentFee = 0;
-      for (const node of equipmentNodes) {
-        const data = node.data;
-        if (cbTools.isUnDef(data.feesIndex) || _.isEmpty(data.feesIndex) ||
-          cbTools.isUnDef(data.feesIndex[feeField]) || cbTools.isUnDef(data.feesIndex[feeField][subFeeField])) {
-          continue;
-        }
-        totalEquipmentFee = (totalEquipmentFee + data.feesIndex[feeField][subFeeField]).toDecimal(decimalObj.process);
-      }
-      baseFee = (baseFee - totalEquipmentFee).toDecimal(decimalObj.process);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender);
+      baseFee = (baseFee - equipmentFee).toDecimal(decimalObj.process);
       return baseFee.toDecimal(decimalObj.bills.totalPrice);
     },
-    // 定额建筑安装工程费(含定额设备购置费*40%) 取固定类别是“建筑安装工程费”的金额,扣除定额设备购置费*60%的金额
+    // 定额建筑安装工程费(含定额设备购置费*40%) 取固定类别是“建筑安装工程费”的定额建安费,扣除定额设备购置费*60%的定额设备费。
     DEJZAZGCFSBSS(tender) {
-      let baseFee = this['JZAZGCF'](tender);
+      let baseFee = this['DEJZAZGCF'](tender);
       const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
-      const allSubNodes = [];
-      projectObj.project.mainTree.getAllSubNode(fixedNode, allSubNodes);
-      const equipmentNodes = allSubNodes.filter(node => node.data.type === rationType.gljRation && node.data.subType === gljType.EQUIPMENT);
-      const feeField = 'common';
-      const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
-      let totalEquipmentFee = 0;
-      for (const node of equipmentNodes) {
-        const data = node.data;
-        if (cbTools.isUnDef(data.feesIndex) || _.isEmpty(data.feesIndex) ||
-          cbTools.isUnDef(data.feesIndex[feeField]) || cbTools.isUnDef(data.feesIndex[feeField][subFeeField])) {
-          continue;
-        }
-        totalEquipmentFee = (totalEquipmentFee + data.feesIndex[feeField][subFeeField]).toDecimal(decimalObj.process);
-      }
-      baseFee = (baseFee - totalEquipmentFee * 0.6).toDecimal(decimalObj.process);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      baseFee = (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.process);
       return baseFee.toDecimal(decimalObj.bills.totalPrice);
     },
-    // 定额建筑安装工程费(不含定额设备购置费、专项费用) 算法:取固定类别是“建筑安装工程费”的金额,扣除定额设备购置费和专项费用的金额
+    // 定额建筑安装工程费(不含定额设备购置费、专项费用) 算法:取固定类别是“建筑安装工程费”的定额建安费,扣除定额设备购置费和专项费用的建安费
     DEJZAZGCFBHSBZX(tender) {
-      let baseFee = this['JZAZGCF'](tender);
+      let baseFee = this['DEJZAZGCF'](tender);
       const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
-      const allSubNodes = [];
-      projectObj.project.mainTree.getAllSubNode(fixedNode, allSubNodes);
-      const equipmentNodes = allSubNodes.filter(node => node.data.type === rationType.gljRation && node.data.subType === gljType.EQUIPMENT);
-      const feeField = 'common';
-      const subFeeField = tender ? 'tenderTotalFee' : 'totalFee';
-      let diffFee = 0;
-      for (const node of equipmentNodes) {
-        const data = node.data;
-        if (cbTools.isUnDef(data.feesIndex) || _.isEmpty(data.feesIndex) ||
-          cbTools.isUnDef(data.feesIndex[feeField]) || cbTools.isUnDef(data.feesIndex[feeField][subFeeField])) {
-          continue;
-        }
-        diffFee = (diffFee + data.feesIndex[feeField][subFeeField]).toDecimal(decimalObj.process);
-      }
-      const specialFee = cbTools.getBaseFee(fixedFlag.SPECIAL_COST, tender, 'common');
-      diffFee = (diffFee + specialFee).toDecimal(decimalObj.process);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      const specialFee = cbTools.getBaseFee(fixedFlag.SPECIAL_COST, tender, 'rationCommon');
+      const diffFee = (equipmentFee + specialFee).toDecimal(decimalObj.process);
       baseFee = (baseFee - diffFee).toDecimal(decimalObj.process);
       return baseFee.toDecimal(decimalObj.bills.totalPrice);
     },
     // 施工场地建设费 算法:按“定额建筑安装工程费”扣除专项费为基数,以累进办法计算
+    // 【变更】:按【固定类别是“建筑安装工程费”的“定额建安费”,扣除固定类别是“专项费用”的“定额建安费”,扣除“设备”的“定额设备费”*60%】为基数,以累进办法计算
     SGCDJSF(tender) {
       let baseFee = this['DEJZAZGCF'](tender);
-      const specialFee = cbTools.getBaseFee(fixedFlag.SPECIAL_COST, tender, 'common');
+      const specialFee = cbTools.getBaseFee(fixedFlag.SPECIAL_COST, tender, 'rationCommon');
       baseFee = (baseFee - specialFee).toDecimal(decimalObj.process);
+      const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      baseFee = (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.process);
       if (!tender) {
         calcBase.baseProgressiveFee = baseFee;
       }
       return calculateUtil.getProgressiveFee(baseFee, '施工场地建设费', projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
     },
     // 建设单位(业主)管理费 算法:按“定额建筑安装工程费”总和为基数,以累进办法计算
+    // 【变更】:算法:按【固定类别是“建筑安装工程费”的“定额建安费”,扣除“设备”的“定额设备费”*60%】为基数,以累进办法计算。
     JSDWYZGLF(tender) {
-      const baseFee = this['DEJZAZGCF'](tender);
+      let baseFee = this['DEJZAZGCF'](tender);
+      const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      baseFee = (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.process);
       if (!tender) {
         calcBase.baseProgressiveFee = baseFee;
       }
       return calculateUtil.getProgressiveFee(baseFee, '建设单位(业主)管理费', projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
     },
     // 建设项目信息化费 算法:按“定额建筑安装工程费”总和为基数,以累进办法计算
+    // 【变更】:算法:按【固定类别是“建筑安装工程费”的“定额建安费”,扣除“设备”的“定额设备费”*60%】为基数,以累进办法计算。
     JSXMXXHF(tender) {
-      const baseFee = this['DEJZAZGCF'](tender);
+      let baseFee = this['DEJZAZGCF'](tender);
+      const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      baseFee = (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.process);
       if (!tender) {
         calcBase.baseProgressiveFee = baseFee;
       }
       return calculateUtil.getProgressiveFee(baseFee, '建设项目信息化费', projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
     },
     // 工程监理费 算法:按“定额建筑安装工程费”总和为基数,以累进办法计算
+    // 【变更】:算法:按【固定类别是“建筑安装工程费”的“定额建安费”,扣除“设备”的“定额设备费”*60%】为基数,以累进办法计算。 
     GCJLF(tender) {
-      const baseFee = this['DEJZAZGCF'](tender);
+      let baseFee = this['DEJZAZGCF'](tender);
+      const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      baseFee = (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.process);
       if (!tender) {
         calcBase.baseProgressiveFee = baseFee;
       }
       return calculateUtil.getProgressiveFee(baseFee, '工程监理费', projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
     },
     // 设计文件审查费 算法:按“定额建筑安装工程费”总和为基数,以累进办法计算
+    // 【变更】:算法:按【固定类别是“建筑安装工程费”的“定额建安费”,扣除“设备”的“定额设备费”*60%】为基数,以累进办法计算。
     SJWJSCF(tender) {
-      const baseFee = this['DEJZAZGCF'](tender);
+      let baseFee = this['DEJZAZGCF'](tender);
+      const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      baseFee = (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.process);
       if (!tender) {
         calcBase.baseProgressiveFee = baseFee;
       }
       return calculateUtil.getProgressiveFee(baseFee, '设计文件审查费', projectObj.project.property.progressiveInterval, decimalObj.bills.totalPrice, deficiency);
     },
     // 前期工作费 算法:按“定额建筑安装工程费”总和为基数,以累进办法计算
+    // 变更:【算法】:按【固定类别是“建筑安装工程费”的“定额建安费”,扣除“设备”的“定额设备费”*60%】为基数,以累进办法计算。
     QQGZF(tender) {
-      const baseFee = this['DEJZAZGCF'](tender);
+      let baseFee = this['DEJZAZGCF'](tender);
+      const fixedNode = projectObj.project.mainTree.roots.find(node => node.getFlag() === fixedFlag.CONSTRUCTION_INSTALL_FEE);
+      const equipmentFee = cbTools.getEquipmentFee(fixedNode, tender, 'equipment');
+      baseFee = (baseFee - equipmentFee * 0.6).toDecimal(decimalObj.process);
       if (!tender) {
         calcBase.baseProgressiveFee = baseFee;
       }

+ 6 - 1
web/users/html/user-buy.html

@@ -81,9 +81,12 @@
                                             <div class="d-inline-block mr-3">
                                                 <img width="24" src="/web/building_saas/img/vip.png">购买
                                             </div>
-                                            <div class="d-inline-block">
+                                            <div class="d-inline-block mr-3">
                                                 <img width="24" src="/web/building_saas/img/vip2.png">借用
                                             </div>
+                                            <div class="d-inline-block">
+                                                <img width="24" src="/web/building_saas/img/vip3.png">赠送
+                                            </div>
                                         </div>
                                         <!--<p class="card-text">-->
                                         <!--&lt;!&ndash;<ul class="pl-3">-->
@@ -102,6 +105,8 @@
                                                 <img width="38" src="/web/building_saas/img/vip2.png" data-toggle="tooltip" data-placement="bottom" data-original-title="借用">
                                                 <% } else if (compilation.lock !== undefined && compilation.lock === 2) { %>
                                                 <img width="38" src="/web/building_saas/img/vip.png" data-toggle="tooltip" data-placement="bottom" data-original-title="购买">
+                                                <% } else if (compilation.lock !== undefined && compilation.lock === 3) { %>
+                                                <img width="38" src="/web/building_saas/img/vip3.png" data-toggle="tooltip" data-placement="bottom" data-original-title="赠送">
                                                 <% } %>
                                             </div>
                                             <div class="ml-auto text-right">