Browse Source

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

TonyKang 7 years ago
parent
commit
39a8ab75d8
30 changed files with 731 additions and 199 deletions
  1. 6 0
      modules/all_models/projects.js
  2. 8 7
      modules/bills_lib/models/bills_lib_interfaces.js
  3. 28 0
      modules/glj/controllers/glj_controller.js
  4. 1 0
      modules/glj/routes/glj_router.js
  5. 10 0
      modules/pm/controllers/pm_controller.js
  6. 2 0
      modules/pm/routes/pm_route.js
  7. 15 0
      modules/users/controllers/user_controller.js
  8. 10 0
      modules/users/models/user_model.js
  9. 1 0
      modules/users/routes/user_route.js
  10. 13 5
      public/scHintBox.html
  11. 25 9
      public/web/common_util.js
  12. 2 1
      public/web/sheet/sheet_data_helper.js
  13. 4 2
      test/public/test_Box.html
  14. 6 5
      web/building_saas/main/html/main.html
  15. 32 4
      web/building_saas/main/js/models/bills.js
  16. 72 25
      web/building_saas/main/js/models/calc_program.js
  17. 30 15
      web/building_saas/main/js/models/installation_fee.js
  18. 2 2
      web/building_saas/main/js/models/main_consts.js
  19. 111 9
      web/building_saas/main/js/models/project_glj.js
  20. 3 4
      web/building_saas/main/js/models/quantity_detail.js
  21. 8 3
      web/building_saas/main/js/views/calc_base_view.js
  22. 71 43
      web/building_saas/main/js/views/calc_program_manage.js
  23. 23 9
      web/building_saas/main/js/views/glj_view.js
  24. 13 5
      web/building_saas/main/js/views/installation_fee_view.js
  25. 85 9
      web/building_saas/main/js/views/project_glj_view.js
  26. 16 7
      web/building_saas/main/js/views/project_view.js
  27. 25 2
      web/building_saas/main/js/views/sub_view.js
  28. 5 12
      web/building_saas/main/js/views/zmhs_view.js
  29. 48 19
      web/building_saas/pm/html/project-management.html
  30. 56 2
      web/building_saas/pm/js/pm_newMain.js

+ 6 - 0
modules/all_models/projects.js

@@ -7,6 +7,11 @@ const Schema = mongoose.Schema;
 const deleteSchema = require('../all_schemas/delete_schema');
 
 const collectionName = 'projects';
+const shareSchema = new Schema({
+    receiver: String, //userID
+    allowCopy: {type: Boolean, default: false},
+    shareDate: String,
+}, {versionKey: false, _id: false});
 const ProjectSchema = new Schema({
     "ID": Number,
     "ParentID": Number,
@@ -19,6 +24,7 @@ const ProjectSchema = new Schema({
     "compilation": String,
     "deleteInfo": deleteSchema,
     'fullFolder': Array,
+    "shareInfo": [shareSchema],
     "property": {
         type: Schema.Types.Mixed,
         default: {}

+ 8 - 7
modules/bills_lib/models/bills_lib_interfaces.js

@@ -3057,14 +3057,15 @@ billsLibDao.prototype.getStdBillsByCode = async function (data, callback) {
     }
     try{
         let bills = await Bills.findOne({billsLibId: data.billsLibId, code: data.code, deleted: false}, '-_id');
-        //设置清单备注(父项清单补注)
-        if(bills.ParentID != -1){
-            let parentBills = await Bills.findOne({billsLibId: data.billsLibId, ID: bills.ParentID, deleted: false});
-            if(parentBills && parentBills.recharge){
-                bills.recharge = parentBills.recharge;
-            }
-        }
+
         if(bills){
+            //设置清单备注(父项清单补注)
+            if(bills.ParentID != -1){
+                let parentBills = await Bills.findOne({billsLibId: data.billsLibId, ID: bills.ParentID, deleted: false});
+                if(parentBills && parentBills.recharge){
+                    bills.recharge = parentBills.recharge;
+                }
+            }
             //设置项目特征
             let itemCharacters = await ItemCharacter.find({billsLibId: data.billsLibId, deleted: false}, '-_id');
             bills._doc.itemCharacter = [];

+ 28 - 0
modules/glj/controllers/glj_controller.js

@@ -660,6 +660,33 @@ class GLJController extends BaseController {
         }
         res.json(result);
     }
+    async batchUpdateGLJProperty(req, res){
+        let result={
+            error:0
+        };
+        try {
+            let data = req.body.data;
+            data = JSON.parse(data);
+            let tasks = [];
+            for(let key in data){
+                let doc = data[key];
+                let query = {id:parseInt(key)};
+                let task = {updateOne:{filter:query, update :doc}};
+                tasks.push(task);
+            }
+            if(tasks.length > 0){
+                let gljModel = new GLJListModel().model;
+                await gljModel.bulkWrite(tasks);
+            }
+            result.data=data;
+        }catch (err){
+            logger.err(err);
+            result.error=1;
+            result.message = err.message;
+        }
+        res.json(result);
+    }
+
     async batchUpdateConsumption(req,res){
         let result={
             error:0
@@ -707,6 +734,7 @@ class GLJController extends BaseController {
         }
         res.json(result);
     }
+
     async modifyKeyValue(req,res){//修改工料机关键的属性:名称、类型、规格、型号等
         let result={
             error:0

+ 1 - 0
modules/glj/routes/glj_router.js

@@ -25,6 +25,7 @@ router.post('/save-as', gljController.init, gljController.unitPriceSaveAs);
 router.post('/get-composition', gljController.init, gljController.getComposition);
 router.post('/updatePrice', gljController.init, gljController.updateUnitPrice);
 router.post('/batchUpdatePrices', gljController.init, gljController.batchUpdatePrices);
+router.post('/batchUpdateGLJProperty', gljController.init, gljController.batchUpdateGLJProperty);
 router.post('/batchUpdateConsumption', gljController.init, gljController.batchUpdateConsumption);
 router.post('/modifyKeyValue',gljController.init, gljController.modifyKeyValue);
 

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

@@ -419,5 +419,15 @@ module.exports = {
             result.message = err.message;
         }
         res.json(result);
+    },
+    projectShareInfo: async function(req, res){
+        try{
+            let data = JSON.parse(req.body.data);
+            let shareInfo = await projectModel.findOne({ID: data.projectID, $or: [{deleteInfo: null}, {'deleteInfo.deleted': false}]}, 'shareInfo');
+            callback(req, res, 0, 'success', shareInfo);
+        }
+        catch (err){
+            callback(req, res, 1, err, null);
+        }
     }
 };

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

@@ -50,6 +50,8 @@ module.exports = function (app) {
     pmRouter.post('/getGCDatas', pmController.getGCDatas);
     pmRouter.post('/recGC', pmController.recGC);
     pmRouter.post('/delGC', pmController.delGC);
+    //share
+    pmRouter.post('/getProjectShareInfo', pmController.projectShareInfo);
 
     app.use('/pm/api', pmRouter);
 };

+ 15 - 0
modules/users/controllers/user_controller.js

@@ -264,6 +264,21 @@ class UserController extends BaseController {
         }
     }
 
+    /*
+    * 获取用户信息
+    * */
+    async getUserByMobile(req, res){
+        try{
+            let userModel = new UserModel();
+            let data = JSON.parse(req.body.data);
+            let userData = await userModel.findDataByMobile(data.mobile);
+            res.json({error: 0, msg: 'success', data: userData});
+        }
+        catch (err){
+            res.json({error: 1, msg: err, data: null});
+        }
+    }
+
 }
 
 export default UserController;

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

@@ -154,6 +154,16 @@ class UserModel extends BaseModel {
     }
 
     /**
+     * 根据手机号查找数据
+     *
+     * @param {string} mobile
+     * @return {object}
+     */
+    findDataByMobile(mobile) {
+        return this.db.findOne({mobile: mobile});
+    }
+
+    /**
      * 根据userId查找数据
      *
      * @param {string} ssoId

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

@@ -19,6 +19,7 @@ module.exports = function (app) {
     router.get('/preferences', userController.init, userController.preferences);
     router.post('/save-preferences', userController.init, userController.savePreferences);
     router.post('/info', userController.init, userController.saveData);
+    router.post('/getUserByMobile', userController.init, userController.getUserByMobile);
 
     router.post('/getVersionInfo', userController.init, userController.getVersionInfo);
     app.use('/user',router);

+ 13 - 5
public/scHintBox.html

@@ -38,6 +38,11 @@
     const hintBox = {
         value: null,
         btnType: {yes: 1, yesNo: 2, yesNoCancel: 3},
+        defalultEvent: function () {
+            $.bootstrapLoading.end();
+//            alert('defalultEvent');
+            return;
+        },
         init: function (){
             // 事件类
             $("#hintBox_value").unbind();
@@ -55,10 +60,7 @@
                 }
             );
             $('#hintBox_btn_cancel').click(
-                function () {
-                    $.bootstrapLoading.end();
-                    return;
-                }
+                hintBox.defalultEvent
             );
 
             // 显示类
@@ -79,7 +81,9 @@
             $("#hintBox_value").focus();
             $("#hintBox_value").select();
         },
-        infoBox: function (title, caption, btnType, doYes, doNo, btnTextArr, showCrossBtn = true) {
+        infoBox: function (title, caption, btnType,
+                           doYes, doNo = hintBox.defalultEvent,
+                           btnTextArr = null, showCrossBtn = true) {
             this.init();
             if (!showCrossBtn)
                 $('#hintBox_btn_cross').hide();
@@ -149,6 +153,10 @@
             $('#hintBox_btn_yes').show();
             $('#hintBox_btn_yes').click(doOK);   // doOK不能给参数
 
+            $('#hintBox_btn_no').text('取消');
+            $('#hintBox_btn_no').show();
+            $('#hintBox_btn_no').click(hintBox.defalultEvent);
+
             $("#hintBox_form").modal('show');
         }
     };

+ 25 - 9
public/web/common_util.js

@@ -13,25 +13,41 @@ String.prototype.hasSubStr = function (str) {
     return this.toLowerCase().indexOf(str.toLowerCase()) > -1;
 };
 
+// 判断字符串是否是数字形式的字符串
+String.prototype.isNumberStr = function () {
+    return this == +this;
+};
+
 // 树结点计算时,取费会出现值为NaN的情况,导致往父节点汇总(递归相加)会出现错误。
 function parseFloatPlus(value){
     let rst = parseFloat(value);
     return  isNaN(rst) ? 0 : rst;
 };
 
-// 将arr2合并到arr1,并去重复。
-function mergeArr(arr1, arr2){
-    if (arr2.length > 0){
-        for (let e of arr2){
-            if (!arr1.includes(e)) arr1.push(e);
+// 数组合并,并去重复。
+Array.prototype.merge = function (arr) {
+    if (arr.length > 0){
+        for (let e of arr){
+            if (!this.includes(e)) this.push(e);
         };
     }
 };
 
-// 判断 sub 是否是 arr 的子数组。
-function isSubArr(sub, arr){
-    for(var i = 0, len = sub.length; i < len; i++){
-        if(arr.indexOf(sub[i]) == -1) return false;
+// 数组是否包含另一个数组。
+Array.prototype.hasSubArr = function (subArr){
+    for(var i = 0, len = subArr.length; i < len; i++){
+        if(this.indexOf(subArr[i]) == -1) return false;
     }
     return true;
 };
+
+function seqString(num,length){
+    var numstr = num.toString();
+    var l=numstr.length;
+    if (numstr.length>=length) {return numstr;}
+
+    for(var  i = 0 ;i<length - l;i++){
+        numstr = "0" + numstr;
+    }
+    return numstr;
+}

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

@@ -55,8 +55,9 @@ var SheetDataHelper = {
         spread.options.allowContextMenu = false;
         spread.options.allowUserDragDrop = false;
         spread.options.allowUndo = false;//that.mainSpread.commandManager().setShortcutKey(undefined, GC.Spread.Commands.Key.z, true, false, false, false); 屏蔽undo
-        spread.options. allowUserEditFormula = false;
+        spread.options.allowUserEditFormula = false;
         spread.options.showDragFillSmartTag = false;
+        spread.options.defaultDragFillType =GC.Spread.Sheets.Fill.AutoFillType.fillWithoutFormatting;
         spread.getActiveSheet().setRowCount(3);
         return spread;
     },

+ 4 - 2
test/public/test_Box.html

@@ -30,11 +30,13 @@
             });
 
             $("#btnB").click(function(){
-                hintBox.infoBox('操作确认', '确定要删除当前节点吗?', 2, cbYes, cbNo);
+                hintBox.infoBox('操作确认', '确定要删除当前节点吗?', 2, cbYes);
+                // 或: hintBox.infoBox('操作确认', '确定要删除当前节点吗?', 2, cbYes, cbNo);
             });
 
             $("#btnC").click(function(){
-                hintBox.infoBox('多分支选择', '三个按钮是否继续?', 3, cbYes, cbNo, ['你','我','他']);
+                hintBox.infoBox('多分支选择', '三个按钮是否继续?', 3, cbYes, cbNo);
+                // 或: hintBox.infoBox('多分支选择', '三个按钮是否继续?', 3, cbYes, undefined, ['你','我','他']);
             });
 
             $("#btnD").click(function(){

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

@@ -899,6 +899,7 @@
                             <button class="btn btn-secondary btn-sm" id="divOpr">/</button>
                             <button class="btn btn-secondary btn-sm" id="leftOpr">(</button>
                             <button class="btn btn-secondary btn-sm" id="rightOpr">)</button>
+                            <span id="errorInfo" style="margin-left:15px;"></span>
                         </p>
                     </div>
                     <div class="row" id="cbRowDiv">
@@ -1139,7 +1140,7 @@
                 </div>
                 <div class="modal-footer">
                     <button class="btn btn-primary" id="select_position_confirm">确定</button>
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                 </div>
             </div>
         </div>
@@ -1218,12 +1219,12 @@
         </div>
     </div>
 
-    <!--弹出 粘位置选择-->
+    <!--弹出 粘位置选择-->
     <div class="modal fade" id="pastePosition" data-backdrop="static">
         <div class="modal-dialog" role="document">
             <div class="modal-content">
                 <div class="modal-header">
-                    <h5 class="modal-title">粘位置选择</h5>
+                    <h5 class="modal-title">粘位置选择</h5>
                     <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                         <span aria-hidden="true">&times;</span>
                     </button>
@@ -1247,9 +1248,9 @@
                         </div>
                     </div>
                 </div>
-                <div class="modal-footer">
+                <div class="modal-footer" style="justify-content: center">
                     <button class="btn btn-primary" id="paste_confirm">确定</button>
-                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
                 </div>
             </div>
         </div>

+ 32 - 4
web/building_saas/main/js/models/bills.js

@@ -506,14 +506,42 @@ var Bills = {
                 return false;
             }
         };
-        bills.prototype.isEngineerEst = function (node) {//判断是否是“专业工程暂估价”节点
-            return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.ENGINEERING_ESITIMATE;
+        bills.prototype.nodeFlagCheck = function (node,fixedFlag) {//判断节点类型
+            let flagCheck = function (checkNode) {
+                if(isFlag(checkNode.data)&&checkNode.data.flagsIndex.fixed.flag==fixedFlag){
+                    return true;
+                }else {
+                    if(checkNode.parent){
+                        return flagCheck(checkNode.parent);
+                    }else {
+                        return false;
+                    }
+                }
+            };
+            return flagCheck(node);
+        };
+
+        bills.prototype.getNodeByFlag = function(node,flag){//取节点类型,返回本身或父项节点
+            if(node){
+                if(isFlag(node.data)&&node.data.flagsIndex.fixed.flag==flag){
+                    return node;
+                }else {
+                    return this.getNodeByFlag(node.parent,flag);
+                }
+            }else {
+                return null;
+            }
+        };
+
+        bills.prototype.isEngineerEst = function (node) {//判断是否是“专业工程暂估价”节点或者子项
+           return this.nodeFlagCheck(node,fixedFlag.ENGINEERING_ESITIMATE);
+            //return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.ENGINEERING_ESITIMATE;
         };
         bills.prototype.isTotalService = function (node) {//判断是否是“总承包服务费”节点
-            return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.TURN_KEY_CONTRACT;
+            return this.nodeFlagCheck(node,fixedFlag.TURN_KEY_CONTRACT);
         };
         bills.prototype.isClaimVisa = function (node) {//判断是否是“签证及索赔计价”节点
-            return node && isFlag(node.data)&&node.data.flagsIndex.fixed.flag==fixedFlag.CLAIM_VISA;
+            return this.nodeFlagCheck(node,fixedFlag.CLAIM_VISA);
         };
         bills.prototype.isMeasure = function (node) {//判读是否属于措施项目部分
             let rootNode = this.getRootNode(node);

+ 72 - 25
web/building_saas/main/js/models/calc_program.js

@@ -707,10 +707,14 @@ let calcTools = {
         glj.tenderQuantity = (glj.quantity * qCoe).toDecimal(decimalObj.glj.quantity);
     },
     calcGLJTenderPrice: function (glj) {
-        let pCoe = 1;
-        if (projectObj.project.property.tenderSetting && projectObj.project.property.tenderSetting.gljPriceTenderCoe)
-            pCoe = projectObj.project.property.tenderSetting.gljPriceTenderCoe;
-        glj.tenderPrice = (glj.marketPrice * pCoe).toDecimal(decimalObj.glj.unitPrice);
+        // let pCoe = 1;
+        // if (projectObj.project.property.tenderSetting && projectObj.project.property.tenderSetting.gljPriceTenderCoe)
+        //     pCoe = projectObj.project.property.tenderSetting.gljPriceTenderCoe;
+        // if (compositionTypes.indexOf(glj.type) >= 0)
+        //
+        // else
+        //     glj.tenderPrice = (glj.marketPrice * pCoe).toDecimal(decimalObj.glj.unitPrice);
+        glj.tenderPrice = projectObj.project.projectGLJ.getTenderMarketPrice(projectObj.project.projectGLJ.getDataByID(glj.projectGLJID));
     },
     // 界面显示的工料机价格,包括定额价、市场价等。参数 price 传入一个普通的价格数值即可。
     uiGLJPrice: function (price){
@@ -728,8 +732,14 @@ let calcTools = {
     getRationsByProjectGLJ(PGLJID){
         let rationIDs = [];
         let RGs = projectObj.project.ration_glj.datas;
+        let PGLJIDs = [];
+        if(Array.isArray(PGLJID)){//为了提高效率,改成支持传入数组
+            PGLJIDs = PGLJID
+        }else {
+            PGLJIDs = [PGLJID];
+        }
         for (let rg of RGs){
-            if (rg.projectGLJID == PGLJID){
+            if (PGLJIDs.indexOf(rg.projectGLJID) !== -1){
                 rationIDs.push(rg.rationID);
             }
         };
@@ -743,7 +753,7 @@ let calcTools = {
         // 工料机形式的定额
         let items = projectObj.project.mainTree.items;
         for (let item of items){
-            if (item.data.projectGLJID == PGLJID)
+            if (PGLJIDs.indexOf(item.data.projectGLJID)  !== -1)
                 rationNodes.push(item);
         };
 
@@ -899,6 +909,7 @@ const rationCalcBases = {
 };
 
 let analyzer = {
+    error: '',
     standard: function(expr){
         let str = expr;
         str = str.replace(/\s/g, "");               // 去空格、去中文空格
@@ -942,8 +953,18 @@ let analyzer = {
         return template.calcItems[idx];
     },
     isCycleCalc: function (expression, ID, template) {     // 这里判断expression,是ID引用: @5+@6
-        if (expression.includes(`@${ID}`))
-            return true;
+        let atID = `@${ID}`;
+        // 避免部分匹配,如:@10匹配@1
+        let idx = expression.indexOf(atID);
+        if (idx >= 0){
+            let nextPos = idx + atID.length;
+            if (nextPos >= expression.length)
+                return true;
+
+            let char = expression.charAt(nextPos);
+            if (!char.isNumberStr())
+                return true;
+        };
 
         let atIDs = analyzer.getAtIDArr(expression);
         for (let atID of atIDs) {
@@ -960,6 +981,7 @@ let analyzer = {
             try {
                 expr = expr.replace(/\[[\u4E00-\u9FA5]+\]/gi, '0');
                 expr = expr.replace(/@\d+/gi, '0');
+                expr = expr.replace(/L/gi, '0');
                 if (expr.includes('00'))
                     return false;
 
@@ -975,14 +997,16 @@ let analyzer = {
         let expr = me.standard(dispExpr);
         let invalidChars = /[^0-9\u4e00-\u9fa5\+\-\*\/\(\)\.\[\]FL%]/g;
         if (invalidChars.test(expr)){
-            hintBox.infoBox('错误提示',`表达式中含有${hintBox.font('无效字符')}!`,1);
+            analyzer.error = `表达式中含有${hintBox.font('无效字符')}!`;
+            // hintBox.infoBox('错误提示',`表达式中含有${hintBox.font('无效字符')}!`,1);
             return false;
         };
 
         let i = expr.search(/\df/ig);   // 4F3
         let j = expr.search(/\d\[/ig);  // 4[定额基价人工费]
         if (i > -1 || j > -1){
-            hintBox.infoBox('错误提示', `表达式中${hintBox.font('缺少运算符')}!`, 1);
+            analyzer.error = `表达式中${hintBox.font('缺少运算符')}!`;
+            // hintBox.infoBox('错误提示', `表达式中${hintBox.font('缺少运算符')}!`, 1);
             return false;
         }
 
@@ -991,26 +1015,30 @@ let analyzer = {
         let pattBase = new RegExp(/\[[\u4E00-\u9FA5]+\]/gi);
         let arrBase = expr.match(pattBase);
         if (arrCn && !arrBase){
-            hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
+            analyzer.error = `定额基数必须用中括号${hintBox.font('[]')}括起来!`;
+            // hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
             return false;
         };
         if (arrCn && arrBase && (arrCn.length != arrBase.length)){
             for (let cn of arrCn){
                 let tempBase = `[${cn}]`;
                   if (!arrBase.includes(tempBase)){
-                      hintBox.infoBox('错误提示', `定额基数“${hintBox.font(cn)}”必须用中括号${hintBox.font('[]')}括起来!`, 1);
+                      analyzer.error = `定额基数“${hintBox.font(cn)}”必须用中括号${hintBox.font('[]')}括起来!`;
+                      // hintBox.infoBox('错误提示', `定额基数“${hintBox.font(cn)}”必须用中括号${hintBox.font('[]')}括起来!`, 1);
                       return false;
                   }
             };
             // 这里要加一个保险。因为上面的 for 循环在“主材费 + [主材费]” 情况下有Bug
-            hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
+            analyzer.error =`定额基数必须用中括号${hintBox.font('[]')}括起来!`;
+            // hintBox.infoBox('错误提示', `定额基数必须用中括号${hintBox.font('[]')}括起来!`, 1);
             return false;
         };
         if (arrBase){
             for (let base of arrBase){
                 let baseName = base.slice(1, -1);
                 if (!rationCalcBases[baseName]){
-                    hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}末定义!`, 1);
+                    analyzer.error = `定额基数${hintBox.font('[' +baseName + ']')}末定义!`;
+                    // hintBox.infoBox('错误提示', `定额基数${hintBox.font('[' +baseName + ']')}末定义!`, 1);
                     return false;
                 }
             };
@@ -1021,18 +1049,21 @@ let analyzer = {
             let num = F.slice(1);
             if (num > template.calcItems.length){
                 let s = hintBox.font('F'+num);
-                hintBox.infoBox('错误提示', `表达式中 “${hintBox.font(s)}” 行号引用错误!`, 1);
+                analyzer.error = `表达式中 “${hintBox.font(s)}” 行号引用错误!`;
+                // hintBox.infoBox('错误提示', `表达式中 “${hintBox.font(s)}” 行号引用错误!`, 1);
                 return false;
             };
         };
 
         let expression = me.getExpression(expr, template);
         if (me.isCycleCalc(expression, itemID, template)){
-            hintBox.infoBox('错误提示', `表达式中有${hintBox.font('循环计算')}!`, 1);
+            analyzer.error = `表达式中有${hintBox.font('循环计算')}!`;
+            // hintBox.infoBox('错误提示', `表达式中有${hintBox.font('循环计算')}!`, 1);
             return false;
         };
         if (!testValue(expression)){
-            hintBox.infoBox('错误提示', `表达式中有${hintBox.font('语法错误')}!`, 1);
+            analyzer.error = `表达式中有${hintBox.font('语法错误')}!`;
+            // hintBox.infoBox('错误提示', `表达式中有${hintBox.font('语法错误')}!`, 1);
             return false;
         };
 
@@ -1136,6 +1167,17 @@ let analyzer = {
         }
         return false;
     },
+    refreshUsedCalcItemsStatement: function(template, calcItem){
+        let atID = '@' + calcItem.ID;
+        for (var i = 0; i < template.calcItems.length; i++) {
+            let item = template.calcItems[i];
+            let atIDArr = analyzer.getAtIDArr(item.expression);
+            if (atIDArr.indexOf(atID) >= 0){
+                item.statement = analyzer.getStatement(item.expression, template);
+            };
+        }
+    },
+
     calcItemLabourCoe: function(calcItem){
         let lc = 0;
         if (calcItem.labourCoeID)
@@ -1158,7 +1200,7 @@ let analyzer = {
         return MaxID;
     },
     templateNewName: function (name) {
-        let i = 2;
+        let i = 1;
         while (projectObj.project.calcProgram.compiledTemplateMaps[name + i]) {
             i++;
         };
@@ -1821,11 +1863,11 @@ class CalcProgram {
                 leafBills.push(leafBill);
         };
 
-        mergeArr(billNodes, leafBills);
+        billNodes.merge(leafBills);
 
         for (let bill of billNodes){
             let changeBills = me.calculate(bill, true, false, tender);
-            mergeArr(allChangedNodes, changeBills);
+            allChangedNodes.merge(changeBills);
         };
 
         me.calcFormulaNodes(allChangedNodes, tender);
@@ -1867,7 +1909,7 @@ class CalcProgram {
             };
 
             let curChangeds = me.calculate(treeNode, true, true, tender);
-            mergeArr(changedNodes, curChangeds);
+            changedNodes.merge(curChangeds);
             me.saveNodes(changedNodes);
         };
     };
@@ -1906,9 +1948,11 @@ class CalcProgram {
 
     // 反向调价
     calcTenderReverse(treeNode, tender){
-        if (treeNode.data.feesIndex.common.tenderUnitFee != treeNode.data.feesIndex.common.unitFee){
-            treeNode.data.feesIndex.common.tenderUnitFee = treeNode.data.feesIndex.common.unitFee;
-            treeNode.changed = true;
+        if (tender == tenderTypes.ttReverseRation) {
+            if (treeNode.data.feesIndex.common.tenderUnitFee != treeNode.data.feesIndex.common.unitFee) {
+                treeNode.data.feesIndex.common.tenderUnitFee = treeNode.data.feesIndex.common.unitFee;
+                treeNode.changed = true;
+            }
         };
 
         if (!treeNode.data.targetTotalFee){
@@ -1921,9 +1965,12 @@ class CalcProgram {
             }
         };
 
+        if (!treeNode.data.targetUnitFee)
+            treeNode.data.targetUnitFee = (treeNode.data.targetTotalFee / treeNode.data.quantity).toDecimal(decimalObj.decimal('unitPrice', treeNode));
         let coe = 1;
         if (treeNode.data.feesIndex.common.totalFee != 0)
-            coe = (treeNode.data.targetTotalFee / treeNode.data.feesIndex.common.totalFee).toDecimal(2);//(decimalObj.process);
+            // coe = (treeNode.data.targetTotalFee / treeNode.data.feesIndex.common.totalFee).toDecimal(decimalObj.process);
+            coe = (treeNode.data.targetUnitFee / treeNode.data.feesIndex.common.unitFee).toDecimal(decimalObj.process);
 
         if (tender == tenderTypes.ttReverseRation){
             treeNode.data.tenderQuantity = (treeNode.data.quantity * coe).toDecimal(decimalObj.decimal("quantity", treeNode));

+ 30 - 15
web/building_saas/main/js/models/installation_fee.js

@@ -276,14 +276,15 @@ var installation_fee = {
                 userID: userID
             };
             let oldITypeRations = _.cloneDeep(project.Ration.getAllInstallTypeRation())//取所有旧的安装增加费定额-没有用的要删除
-            let oldRationMap = {}, deleteRationNodes = [], deleteBillsNodes = [];
+            let oldRationMap = {}, deleteRationNodes = [], deleteBillsNodes = [],reCalBillIDS = [];
             let isChange = newBills.length>0;//记录数据是否发生了改变;
-            for(let o of oldITypeRations){//过滤出要删除的定额
+            for(let o of oldITypeRations){//过滤出要删除的定额 - 同时对应的父项也要重新更新计算
                 if(rationKeyMap[o.installationKey]==undefined){
                     updateData.ration.delete.push(o);
                     let d_node =  project.mainTree.getNodeByID(o.ID);
                     if(d_node){
                         deleteRationNodes.push(d_node);
+                        reCalBillIDS.push(o.billsItemID);
                         isChange = true;
                     }
                 }
@@ -302,8 +303,8 @@ var installation_fee = {
                 }
             }
 
-            for(let tem_bx of BXs){//过滤要删除的补项
-                if(usedBXMap[tem_bx.ParentID]==undefined){
+            for(let tem_bx of BXs){//过滤要删除的 自动生成的补项
+                if(tem_bx.code.startsWith('BAZF')&& usedBXMap[tem_bx.ParentID]==undefined){
                     updateData.bills.delete.push(tem_bx);
                     let b_node =  project.mainTree.getNodeByID(tem_bx.ID);
                     if(b_node){
@@ -331,9 +332,16 @@ var installation_fee = {
                         calRations =  addNewNodes(updateData);
                     });
                     for(let u of updateData.ration.update){
-                        let unode =   projectObj.project.mainTree.findNode(u.ID);
+                        let unode =  projectObj.project.mainTree.findNode(u.ID);
                          unode?calRations.push(unode):'';
                     }
+                    if(reCalBillIDS.length > 0){
+                        reCalBillIDS = _.uniq(reCalBillIDS);
+                        for(let bID of reCalBillIDS){
+                            let bnode =  projectObj.project.mainTree.findNode(bID);
+                            bnode?calRations.push(bnode):''; //现在计算程序支持同时传入清单和定额了,所以能放一起
+                        }
+                    }
                     setTreeSelection(selectedNode);
                     let endTime =  +new Date();
                     console.log(`计算安装增加费时间——${endTime - startTime}`);
@@ -493,13 +501,13 @@ var installation_fee = {
                             projectID: parseInt(project.ID()),
                             ParentID:billID_key,
                             NextSiblingID:-1,
-                            code : 'BAZF',
                             name:'安装增加费',
                             unit:'元',
                             quantity:'1',
                             type:billType.BX
                         };
                         BXNodeData.ID =  uuid.v1();
+                        BXNodeData.code = getBXCode("BAZF",usedBXMap);
                         FBMap[billID_key] = BXNodeData;
                         newBills.push(BXNodeData);
                     }
@@ -519,6 +527,22 @@ var installation_fee = {
                 }
             }
 
+            function getBXCode(code,BXMap) {//自动生成物补项编号加001、002等后缀
+                let codes = [];
+                let i = 1;
+                let newCode = '';
+                for(let key in BXMap){
+                    codes.push(BXMap[key].code);
+                }
+                while (true){
+                    newCode = code + seqString(i,3);
+                    if(codes.indexOf(newCode)==-1){
+                        break;
+                    }
+                    i++;
+                }
+               return newCode;
+            }
 
             function allInOne(item,rule,rations,newBills,pre_key,rationKeyMap) {//统一设置
                 let billData = getBillNodeData(item,rule,newBills);//取对应的清单或生成一个新的清单数据
@@ -562,8 +586,6 @@ var installation_fee = {
                 newRationData = setNewRationProperty(newRationData,nextID,rule);
                 return newRationData;
             }
-
-
             function getBillNodeData(item,rule,newBills) {
                 let billData = null;
                 let billID = null;
@@ -590,7 +612,6 @@ var installation_fee = {
             function getBillsByID(billID){
                 return _.find(allBillsDatas,{"ID":billID});
             }
-
             function getBillsByCode(code){
                 return _.find(allBillsDatas, function(b) {
                     if(b.code&&b.code.indexOf(code)!=-1){
@@ -600,8 +621,6 @@ var installation_fee = {
                     }
                 })
             }
-
-
             function calcQuantity(rule,ration) {//计算单条定额的三个消耗量
                 let gljDecimal = getDecimal('glj.quantity');
                 let labourQuantity = 0, materialQuantity = 0, machineQuantity = 0;
@@ -718,10 +737,6 @@ var installation_fee = {
             });
         };
 
-
-
-
-
         installation_fee.prototype.resetToDefault = function (callback) {
             let me = this;
             let installFees = [];

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

@@ -73,7 +73,7 @@ const allMaterialTypes = [
     gljType.MAIN_MATERIAL,
     gljType.EQUIPMENT
 ];
-// 会有组成物的材料
+// 会有组成物的材料、机械台班
 const compositionTypes = [
     gljType.MAIN_MATERIAL,
     gljType.CONCRETE,
@@ -100,7 +100,7 @@ const CP_Col_Width = {          // 多处计算程序界面的列宽统一设置
     feeRate: 60,
     displayFieldName: 120,
     statement: 380,
-    memo: 110,
+    memo: 120,
     unitFee: 90,
     totalFee: 90
 };

+ 111 - 9
web/building_saas/main/js/models/project_glj.js

@@ -298,16 +298,68 @@ ProjectGLJ.prototype.updatePrice = function (recode, updateField, newval,from,cb
     }
 };
 
-ProjectGLJ.prototype.batchUpdatePrice = function (changeInfo,callback) {
+ProjectGLJ.prototype.batchUpdateGLJProperty = function (updateMap,callback) {
+    let me = this;
+    //更新是否暂估和供货方式时,要做特殊处理
+    $.bootstrapLoading.start();
+    CommonAjax.post("/glj/batchUpdateGLJProperty", updateMap,function (result) {
+        $.bootstrapLoading.end();
+        let supplyChangeIDs = [],evaluate_gljs = [],rationNodes = [];
+        console.log(updateMap);
+        for(let idKey in updateMap){
+            let gljID = parseInt(idKey);
+            let glj = me.getByID(gljID);
+            let doc = updateMap[idKey];
+            for(let property in doc){
+                glj[property] = doc[property];
+            }
+            if(doc.hasOwnProperty("supply")||doc.hasOwnProperty("supply_quantity")){
+                supplyChangeIDs.push(gljID);
+            }
+            if(doc.hasOwnProperty("is_evaluate")){
+                evaluate_gljs.push(glj);
+            }
+        }
+        if(supplyChangeIDs.length>0){
+            let temRationNodes = calcTools.getRationsByProjectGLJ(supplyChangeIDs);
+            if (temRationNodes.length > 0) rationNodes = rationNodes.concat(temRationNodes);
+        }
+        if(evaluate_gljs.length > 0){
+            let [impactRationNodes,impactGLJs] = me.batchChangeIsEvaluate(evaluate_gljs);
+            rationNodes = rationNodes.concat(impactRationNodes);
+        }
+
+        if(rationNodes.length > 0){
+            rationNodes = _.uniq(rationNodes,'data');
+            projectObj.project.calcProgram.calcNodesAndSave(rationNodes, function () {
+                projectObj.mainController.refreshTreeNode(projectObj.project.mainTree.roots);
+            });
+        }
+
+        if(callback){
+            callback();
+        }
+
+    })
+
+
+};
+
+ProjectGLJ.prototype.batchUpdatePrice = function (changeInfo,sheetName,callback) {
     let me = this;
     let projectGljs = me.datas.gljList;
     let decimal = getDecimal('glj.unitPrice');
     let updateData = [];
     let newValueMap = {};
     let gljs=[];
+    let setting = sheetName =="materialTreeSheet"?projectGljObject.materialSetting:projectGljObject.projectGljSetting;
+    if(changeInfo.length<=0){
+        callback?callback():'';
+        return
+    }
     for(let ci of changeInfo){
-        let dataCode = projectGljObject.projectGljSetting.header[ci.col].dataCode;
-        let recode = projectGljObject.projectGljSheetData[ci.row];
+        let dataCode = setting.header[ci.col].dataCode;
+        let recode = sheetName =="materialTreeSheet"?projectGljObject.materialTree.items[ci.row].data:projectGljObject.projectGljSheetData[ci.row];
         if(dataCode=='basePrice'||dataCode=='marketPrice'){
             let editField = dataCode === 'basePrice'?"base_price":"market_price";
             let newValue= scMathUtil.roundForObj(ci.value,decimal);
@@ -532,8 +584,8 @@ ProjectGLJ.prototype.changeIsEvaluate=function (id){
     let datas = projectGLJ.datas;
     let gljList = datas.gljList;
     let glj = _.find(gljList, {'id': id});
-    if(glj){
-        let con_key = gljOprObj.getIndex(glj,gljKeyArray);
+    if(glj){//与批量更新调用相同的方法
+     /*   let con_key = gljOprObj.getIndex(glj,gljKeyArray);
         let pratioM =datas.mixRatioConnectData[con_key];//找到父key
         let conditions = [];
         if(pratioM&&pratioM.length>0){
@@ -559,11 +611,55 @@ ProjectGLJ.prototype.changeIsEvaluate=function (id){
             rg.data.isEstimate =glj.is_evaluate?1:0;
             ration_nodes.push(rg);
         }
-        ration_nodes.length>0?projectObj.mainController.refreshTreeNode(ration_nodes):"";
+        ration_nodes.length>0?projectObj.mainController.refreshTreeNode(ration_nodes):"";*/
+        let [nodes,gljs] = projectGLJ.batchChangeIsEvaluate([glj]);
         projectObj.project.calcProgram.calcNodesAndSave(nodes);//触发计算程序
         return gljs;
     }
-}
+};
+
+/**
+ * 批量更新是否暂估
+ *传入项目工料机数组
+ */
+
+ProjectGLJ.prototype.batchChangeIsEvaluate=function (gljs){
+    let impactGLJs = [], changeArray =_.map(gljs,'id'),changeMap = _.indexBy(gljs,'id');;
+    for(let glj of gljs){
+        let con_key = gljOprObj.getIndex(glj,gljKeyArray);
+        let pratioM =this.datas.mixRatioConnectData[con_key];//找到父key
+        let conditions = [];
+        if(pratioM&&pratioM.length>0){
+            for(let p_key of pratioM ){
+                conditions.push(gljOprObj.getConditionByKey(p_key));
+            }
+        }
+        let tem_gljs = this.getProjectGLJs(conditions,false);
+        if(tem_gljs.length > 0) impactGLJs = impactGLJs.concat(tem_gljs);
+    }
+    impactGLJs = impactGLJs.concat(gljs);
+    impactGLJs =  _.uniq(impactGLJs,'id');//去重复
+
+    let impactRationNodes = this.getImpactRationNodes(impactGLJs);
+    let neeRefreshNode = [];
+    //更新对应的工料机类型的定额
+    for(let item of projectObj.project.Ration.datas){
+        if(item.type == rationType.gljRation && changeArray.indexOf(item.projectGLJID) != -1){
+            let tem_g = changeMap[item.projectGLJID];
+            item.isEstimate =tem_g.is_evaluate?1:0;
+            let ration_node = projectObj.project.mainTree.getNodeByID(item.ID);
+            neeRefreshNode?neeRefreshNode.push(ration_node):'';
+        }
+    }
+    let ration_glj_nodes = this.getMainAndEquGLJNodeByID(changeArray);//取显示在造价书界面上的主材和设备节点
+    for(let rg of ration_glj_nodes){
+        let tem_g = changeMap[rg.data.projectGLJID];
+        rg.data.isEstimate =tem_g.is_evaluate?1:0;
+        neeRefreshNode.push(rg);
+    }
+    neeRefreshNode.length>0?projectObj.mainController.refreshTreeNode(neeRefreshNode):"";
+    return [impactRationNodes,impactGLJs];
+};
 
 ProjectGLJ.prototype.getByID = function (ID) {
     return _.find(this.datas.gljList,{'id':ID});
@@ -591,9 +687,15 @@ ProjectGLJ.prototype.refreshTreeNodePriceIfNeed = function (data) {
 
 ProjectGLJ.prototype.getMainAndEquGLJNodeByID = function (id) {//通过ID取显示到主树上的主材和设备节点
     let nodes = [];
+    let ids = [];
+    if(Array.isArray(id)){
+        ids = id;
+    }else {
+        ids = [id];
+    }
     if(projectInfoObj.projectInfo.property.displaySetting.disPlayMainMaterial == true){
          nodes = _.filter(projectObj.project.mainTree.items, function (tem) {
-            return tem.sourceType == ModuleNames.ration_glj && tem.data.projectGLJID == id
+            return tem.sourceType == ModuleNames.ration_glj && ids.indexOf(tem.data.projectGLJID)  !== -1
         })
     }
     return nodes;
@@ -736,7 +838,7 @@ ProjectGLJ.prototype.isEstimateType = function(type){
 
 ProjectGLJ.prototype.getShortNameByID = function (ID) {
     let gljTypeMap = this.datas.constData.gljTypeMap;
-    return gljTypeMap["typeId" + ID].shortName;
+    return gljTypeMap["typeId" + ID]?gljTypeMap["typeId" + ID].shortName:'';
 };
 
 ProjectGLJ.prototype.calcQuantity  = function (init=false){

+ 3 - 4
web/building_saas/main/js/models/quantity_detail.js

@@ -626,7 +626,6 @@ var quantity_detail = {
             }else {
                 me.updateRationQuantity(value,node,null,editingText);
             }
-            gljOprObj.refreshView();
         };
 
 
@@ -677,6 +676,7 @@ var quantity_detail = {
                     project.projectGLJ.loadData();
                 });*/
                 project.calcProgram.calcNodesAndSave(needUpdateChildren, function () {
+                    project.projectGLJ.calcQuantity();
                     if(project.Bills.isFBFX(node)) { //判断是否属于分部分项工程 ,是的话才需要做计取安装费计算
                         project.installation_fee.calcInstallationFee(function (isChange,rations) {
                             if(isChange){
@@ -685,8 +685,6 @@ var quantity_detail = {
                                 });
                             }
                         });
-                    }else {
-                        project.projectGLJ.calcQuantity();
                     }
                 });
 
@@ -699,6 +697,7 @@ var quantity_detail = {
             if(gljNodes.length>0){
                 projectObj.mainController.refreshTreeNode(gljNodes);
             }
+            gljOprObj.refreshView();
         };
         quantity_detail.prototype.updateRationQuantity=function(value,node,quantityEXP,editingText){
             node.data.quantityEXP = quantityEXP?quantityEXP:editingText;
@@ -724,7 +723,7 @@ var quantity_detail = {
                 }
             });
             projectObj.mainController.refreshTreeNode(node.children);//刷新子工料机总消耗量
-            gljOprObj.showRationGLJSheetData();
+            gljOprObj.refreshView();
         };
         quantity_detail.prototype.getDecimal=function (node) {
             var decimal = 3;

+ 8 - 3
web/building_saas/main/js/views/calc_base_view.js

@@ -236,9 +236,10 @@ let calcBaseView = {
             operators[i].bind('click', function () {
                 let v = $(this)[0].textContent;
                 let insertStr = me.insertStr(v);
-                if(me.arithmeticLegal(insertStr)){
+                me.inputExpr.val(insertStr);
+                /*if(me.arithmeticLegal(insertStr)){
                     me.inputExpr.val(insertStr);
-                }
+                }*/
                 me.inputExpr.focus();
             });
         }
@@ -314,6 +315,9 @@ let calcBaseView = {
                                 $.bootstrapLoading.end();
                             }
                         });
+                    }
+                    else{
+                        $('#errorInfo').html(analyzer.error);
                     };
                 }
                 else
@@ -408,6 +412,7 @@ $(document).ready(function () {
     });
 
     $('#qd-jsjs').on('hidden.bs.modal', function () {
+        $('#errorInfo').text('');
         //清空输入框
         calcBaseView.inputExpr.val('');
         calcBaseView.workBook.destroy();
@@ -422,7 +427,7 @@ $(document).ready(function () {
     calcBaseView.clickOpr([$('#addOpr'), $('#subOpr'), $('#mulOpr'), $('#divOpr'), $('#leftOpr'), $('#rightOpr')]);
 
     //bind input control
-    calcBaseView.inputControl();
+    //calcBaseView.inputControl();
 
     //confirmBtn
     calcBaseView.calcBaseConf();

+ 71 - 43
web/building_saas/main/js/views/calc_program_manage.js

@@ -60,6 +60,7 @@ let calcProgramManage = {
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.ValueChanged, me.onDetailValueChanged);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.RangeChanged, me.onRangeChanged);
         me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.EnterCell, me.onDetailEnterCell);
+        me.detailSpread.getSheet(0).bind(GC.Spread.Sheets.Events.ClipboardPasting, me.onClipboardPasting);
 
         let mSheet = me.mainSpread.getSheet(0);
         sheetCommonObj.showData(mSheet, me.mainSetting, me.datas);
@@ -135,18 +136,35 @@ let calcProgramManage = {
         };
 
         curCalcItem[dataCode] = args.newValue;
-        let data = {
-            'projectID': projectObj.project.ID(),
-            'templatesID': template.ID,
-            'calcItem': curCalcItem
-        };
-        me.saveCalcItem(data, function (rst) {
-            if (rst){
-                let relationNodes = calcTools.getNodesByProgramID(template.ID);
-                projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
-            }
-        });
-        $.bootstrapLoading.end();
+
+        if (dataCode == 'name'){
+            analyzer.refreshUsedCalcItemsStatement(template, curCalcItem);
+            let data = {
+                'projectID': projectObj.project.ID(),
+                'ID': template.ID,
+                'calcItems': template.calcItems
+            };
+            calcProgramManage.updateTemplate(data, function (rst) {
+                if (rst){
+                    calcProgramManage.refreshDetailSheet();
+                    $.bootstrapLoading.end();
+                }
+            });
+        }
+        else{
+            let data = {
+                'projectID': projectObj.project.ID(),
+                'templatesID': template.ID,
+                'calcItem': curCalcItem
+            };
+            me.saveCalcItem(data, function (rst) {
+                if (rst){
+                    let relationNodes = calcTools.getNodesByProgramID(template.ID);
+                    projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
+                    $.bootstrapLoading.end();
+                }
+            });
+        }
     },
     onDetailEnterCell: function (sender, args) {
         // for test.
@@ -159,6 +177,9 @@ let calcProgramManage = {
         // let e = `ID:${c.ID} ${c.expression} ${c.dispExpr} ${c.dispExprUser} ${c.compiledExpr} ${c.custom}`;
         // projectObj.testDisplay('', e);
     },
+    onClipboardPasting: function (sender, args) {
+         args.cancel = true;
+    },
     loadMainContextMenu: function () {
         $.contextMenu({
             selector: '#mainSpread',
@@ -216,7 +237,7 @@ let calcProgramManage = {
                         let idx = calcProgramManage.mainSpread.getActiveSheet().getActiveRowIndex();
 
                         let newName = '';
-                        hintBox.valueBox('请输入新的模板名称:', template.name, function () {
+                        hintBox.valueBox('重命名', template.name, function () {
                             newName = hintBox.value;
 
                             if (!newName){
@@ -243,6 +264,7 @@ let calcProgramManage = {
                             calcProgramManage.updateTemplate(data, function (rst) {
                                 if (rst){
                                     projectObj.project.calcProgram.compileTemplateMaps();
+                                    projectObj.mainController.refreshTreeNode(calcTools.getNodesByProgramID(template.ID));
                                     sheetCommonObj.showData(calcProgramManage.mainSpread.getSheet(0), calcProgramManage.mainSetting, calcProgramManage.datas);
                                     $.bootstrapLoading.end();
                                 }
@@ -260,28 +282,29 @@ let calcProgramManage = {
                         return !canDelete;
                     },
                     callback: function () {
-                        $.bootstrapLoading.start();
                         let template = calcProgramManage.getSelectionInfo().template;
                         if (analyzer.templateIsUsed(template.ID)) {
                             $.bootstrapLoading.end();
                             hintBox.infoBox('系统提示', `计算模板“${template.name}”已被使用,不允许删除!`, 1);
                             return;
-                        }
-                        let data = {
-                            'projectID': projectObj.project.ID(),
-                            'ID': template.ID
                         };
-                        calcProgramManage.deleteTemplate(data, function (rst) {
-                            if (rst){
-                                let idx = calcProgramManage.mainSpread.getActiveSheet().getActiveRowIndex();
-                                projectObj.project.calcProgram.templates.splice(idx, 1);
-                                projectObj.project.calcProgram.compileTemplateMaps();
-                                calcProgramManage.buildSheet();
-                                calcProgramManage.mainSpread.getActiveSheet().setSelection(idx - 1, 0, 1, 1);
-                                calcProgramManage.refreshDetailSheet();
-                            }
-                        });
-                        $.bootstrapLoading.end();
+                        hintBox.infoBox('系统提示', `确定要删除计算模板“${template.name}”吗?`, 2, cbYes);
+                        function cbYes() {
+                            let data = {
+                                'projectID': projectObj.project.ID(),
+                                'ID': template.ID
+                            };
+                            calcProgramManage.deleteTemplate(data, function (rst) {
+                                if (rst){
+                                    let idx = calcProgramManage.mainSpread.getActiveSheet().getActiveRowIndex();
+                                    projectObj.project.calcProgram.templates.splice(idx, 1);
+                                    projectObj.project.calcProgram.compileTemplateMaps();
+                                    calcProgramManage.buildSheet();
+                                    calcProgramManage.mainSpread.getActiveSheet().setSelection(idx - 1, 0, 1, 1);
+                                    calcProgramManage.refreshDetailSheet();
+                                }
+                            });
+                        };
                     }
                 }
             }
@@ -350,21 +373,24 @@ let calcProgramManage = {
                             return;
                         };
 
-                        template.calcItems.splice(idx, 1);
-                        let data = {
-                            'projectID': projectObj.project.ID(),
-                            'ID': template.ID,
-                            'calcItems': template.calcItems
+                        hintBox.infoBox('系统提示', `确定要删除计算规则“${item.name}”吗?`, 2, cbYes);
+                        function cbYes() {
+                            template.calcItems.splice(idx, 1);
+                            let data = {
+                                'projectID': projectObj.project.ID(),
+                                'ID': template.ID,
+                                'calcItems': template.calcItems
+                            };
+                            calcProgramManage.updateTemplate(data, function (rst) {
+                                if (rst){
+                                    projectObj.project.calcProgram.compileTemplate(template);
+                                    calcProgramManage.refreshDetailSheet();
+                                    let relationNodes = calcTools.getNodesByProgramID(template.ID);
+                                    projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
+                                    $.bootstrapLoading.end();
+                                }
+                            });
                         };
-                        calcProgramManage.updateTemplate(data, function (rst) {
-                            if (rst){
-                                projectObj.project.calcProgram.compileTemplate(template);
-                                calcProgramManage.refreshDetailSheet();
-                                let relationNodes = calcTools.getNodesByProgramID(template.ID);
-                                projectObj.project.calcProgram.calcNodesAndSave(relationNodes);
-                            }
-                        });
-                        $.bootstrapLoading.end();
                     }
                 }
             }
@@ -399,11 +425,13 @@ let calcProgramManage = {
         );
     },
     deleteTemplate: function (data, callback) {
+        $.bootstrapLoading.start();
         CommonAjax.post('/calcProgram/deleteTemplate', data,
             function (result) {
                 if(callback){
                     callback(result);
                 }
+                $.bootstrapLoading.end();
             }
         );
     },

+ 23 - 9
web/building_saas/main/js/views/glj_view.js

@@ -560,19 +560,28 @@ var gljOprObj = {
             }
             if (node.sourceType == "ration") {
                 if(node.data.type==rationType.gljRation){
-                    this.showMixRatio(node);
+                    if($('#linkGLJ').hasClass('active')){
+                        this.showMixRatio(node);
+                    }
                 }else {
-                    this.showRationGLJData(node);
-                    installationFeeObj.showRationInstallationData(node);
+                    if($('#linkGLJ').hasClass('active')){
+                        this.showRationGLJData(node);
+                    }
+                    if($('#linkAZZJF').hasClass('active')){
+                        installationFeeObj.showRationInstallationData(node);
+                    }
                 }
                 isShow = true;
             }
             if(node.sourceType == ModuleNames.ration_glj){
-                this.showMixRatio(node);
+                if($('#linkGLJ').hasClass('active')) {
+                    this.showMixRatio(node);
+                }
                 isShow = true;
             }
-
-            this.showQuantityDetailData(node);
+            if($('#linkGCLMX').hasClass('active')){
+                this.showQuantityDetailData(node);
+            }
         } else {
             this.selectedNodeId = null;
         }
@@ -721,6 +730,7 @@ var gljOprObj = {
         var projectGljs = projectGLJData.gljList;
         var mixRatioMap = projectGLJData.mixRatioMap;
         if (ration_gljs && ration_gljs.length > 0 && projectGljs && projectGljs.length > 0) {
+
             for (var i = 0; i < ration_gljs.length; i++) {
                 var glj = _.find(projectGljs, {'id': ration_gljs[i].projectGLJID});
                 if (glj) {
@@ -845,9 +855,13 @@ var gljOprObj = {
         }
     },
     clearSheetData: function () {
-        sheetCommonObj.showData(this.sheet, this.setting, []);
-        installationFeeObj.rationInstallSheet.setRowCount(0);//清除combobox cell
-        sheetCommonObj.showData(installationFeeObj.rationInstallSheet, installationFeeObj.rationInstallSetting, []);
+        if($('#linkGLJ').hasClass('active')){
+            sheetCommonObj.showData(this.sheet, this.setting, []);
+        }
+        if($('#linkAZZJF').hasClass('active')){
+            installationFeeObj.rationInstallSheet.setRowCount(0);//清除combobox cell
+            sheetCommonObj.showData(installationFeeObj.rationInstallSheet, installationFeeObj.rationInstallSetting, []);
+        }
         //  sheetCommonObj.showData(this.detailSheet,this.detailSetting,[]);
         this.sheetData = [];
         installationFeeObj.rationInstallData = [];

+ 13 - 5
web/building_saas/main/js/views/installation_fee_view.js

@@ -331,6 +331,8 @@ let installationFeeObj={
         if(this.feeItemSpread == null){
             this.initInstallationFeeSpread();
         }else {
+            this.feeItemSpread.refresh();
+            this.feeDetailSpread.refresh();
             let sel_f = this.feeItemSheet.getSelections()[0];
             let sel_d = this.feeDetailSheet.getSelections()[0];
             this.showFeeItemData();
@@ -648,11 +650,15 @@ let installationFeeObj={
                recode:me.positionData[args.row]
            }
         }else {
-            if(args.row==me.positionSelectedObject.row){//如果是在已选中的记录中再点一次选中复框,则去掉选中记录
-                me.positionSelectedObject = null;
+            if(me.positionData[args.row].ID == me.positionSelectedObject.recode.ID){//行相同的时候有两种情况,一种是没有做过滤的情况,行相等就说明是要去掉选中记录。
+                // 另外一种有可能是过滤后刚好和初始的选中位置显示的时候相等,这里其实是不同的记录,所以行相等的时候用ID判断是不是来的记录才准确
+                    me.positionSelectedObject = null;  //如果是在已选中的记录中再点一次选中复框,则去掉选中记录
             }else {//切换选中记录
-                //去掉之前选中位置的打勾
-                args.sheet.getCell(me.positionSelectedObject.row, me.positionSelectedObject.col).value(0);
+                //去掉之前选中位置的打勾 - 要先查找原先的位置,因为过滤功能的原因,有可能选中的与当前的行数已经不一样了
+                let oldIndex = _.findIndex(me.positionData,{'ID':me.positionSelectedObject.recode.ID});
+                if(oldIndex != -1){
+                    args.sheet.getCell(oldIndex, me.positionSelectedObject.col).value(0);
+                }
                 me.positionSelectedObject ={
                     row : args.row,
                     col: args.col,
@@ -1364,7 +1370,9 @@ $(function () {
     });
     $('#calc_position').on('shown.bs.modal',function () {
         installationFeeObj.positionSelectedObject = null;
-        if (!installationFeeObj.positionSpread) {
+        if (installationFeeObj.positionSpread) {
+            installationFeeObj.positionSpread.refresh();
+        }else {
             installationFeeObj.initPositionSpread();
         }
         installationFeeObj.loadSelectionNodes();

+ 85 - 9
web/building_saas/main/js/views/project_glj_view.js

@@ -250,6 +250,10 @@ projectGljObject={
         }else if(sheet.name() ==  'materialTreeSheet'){
             data = me.materialTree.selected.data;
             setting = me.materialSetting;
+            let notEditId= ['GC','GJ','MC','SN','SZ'];
+            if(notEditId.indexOf(data.id)!= -1){
+                return false;
+            }
         }
         let dataCode = setting.header[col].dataCode;
         let lockColumns = setting.view.lockColumns;
@@ -342,7 +346,7 @@ projectGljObject={
         if(canChange == false){//恢复原来的值
             info.sheetName =="materialTreeSheet"?me.showMaterialTreeData():me.showProjectGljData();
         }else if(info.sheetName =="projectGljSheet"){
-            me.batchUpdateProjectGLJ(changeInfo);
+            me.batchUpdateProjectGLJ(changeInfo,info.sheetName);
         }
     },
     onMixRatioRangeChange:function (sender,info){
@@ -376,18 +380,90 @@ projectGljObject={
 
 
     },
-    batchUpdateProjectGLJ:function(changeInfo){
+    batchUpdateProjectGLJ:function(changeInfo,sheetName){
         let projectGLJ = projectObj.project.projectGLJ;
         let me = projectGljObject;
-        me.batchUpdateGLJProperty(changeInfo);
-        projectGLJ.batchUpdatePrice(changeInfo,function (impactList) {
-            let selected = me.projectGljSheet.getSelections()[0];
-            me.showProjectGljData();
-            me.projectGljSheet.setSelection(selected.row,selected.col,selected.rowCount,selected.colCount);
+        let propertyCells=[],priceCells=[];
+        let setting = sheetName =="materialTreeSheet"?me.materialSetting:me.projectGljSetting;
+        for(let c of changeInfo){
+            c.dataCode = setting.header[c.col].dataCode;
+            if(c.dataCode == 'basePrice'||c.dataCode=='marketPrice'){
+                priceCells.push(c);
+            }else {
+                propertyCells.push(c);
+            }
+        }
+        me.batchUpdateGLJProperty(propertyCells,sheetName,function () {
+            //价格属于单价文件表,如果与项目工料机的其它属性一起的话计算起来会比较复杂,同时出现价格与其它属性一起更新的情况也会比较少;
+            projectGLJ.batchUpdatePrice(priceCells,sheetName,function (impactList) {
+                me.refreshBySheetName(sheetName);
+                gljOprObj.refreshView();
+            });
         });
     },
-    batchUpdateGLJProperty:function (changeInfo) {
-        console.log(changeInfo)
+    refreshBySheetName:function (sheetName) {
+        let me = projectGljObject;
+        if(sheetName =="projectGljSheet"){
+            me.showProjectGljData();
+        }else if(sheetName =="materialTreeSheet"){
+            me.showMaterialTreeData();
+        }
+    },
+
+    batchUpdateGLJProperty:function (changeInfo,sheetName,callback) {
+        let me = projectGljObject,updateMap = {};
+        let projectGLJ = projectObj.project.projectGLJ;
+        for(let c of changeInfo){
+            let recode = sheetName =="materialTreeSheet"?me.materialTree.items[c.row].data:me.projectGljSheetData[c.row];
+            if(recode[c.dataCode] == c.value){
+                continue;
+            }
+            me.getUpdateData(recode.id,c.value,c.dataCode,c.quantity,updateMap);
+        }
+        if(_.isEmpty(updateMap)){
+            callback?callback():'';
+            return;
+        }
+        projectGLJ.batchUpdateGLJProperty(updateMap,callback);
+    },
+    getUpdateData :function (id,value,dataCode,quantity,updateMap) {
+        let me = projectGljObject;
+        let supplyMap = {"自行采购":0,"部分甲供":1,"完全甲供":2,"甲定乙供":3};
+        let materialMap = {"钢材":1,"钢筋":2,"木材":3,"水泥":4,"标准砖":5};
+        let data = updateMap[id]?updateMap[id]:{};
+        //供货方式 和三材类型 粘贴和填充过来的数据,要做对应转换,因为这里value只是中文文本,并不是实际的值
+        // 如果是供货方式则需要处理数据
+        if (dataCode === 'supply') {
+            if(supplyMap[value]!==undefined||supplyMap[value]!==null){
+                value = supplyMap[value];
+            }
+            data.supply_quantity = me.getSupplyQuantity(value,quantity);
+        }
+        if(dataCode === 'supply_quantity'){//修改数量需做4舍5入
+            value =  scMathUtil.roundForObj(value,getDecimal('glj.quantity'));
+        }
+        if(dataCode === 'is_evaluate'||dataCode === 'is_adjust_price'||dataCode === 'is_main_material'){
+            if(value){
+                value = 1;
+            }else {
+                value = 0;
+            }
+        }
+        if(dataCode === 'materialType'){//三材类型要做对应转换,因为这里value只是中文文本,并不是实际的值
+            if(materialMap[value]!==undefined||materialMap[value]!==null){
+                value =  materialMap[value];
+            }
+            if(value == null || value==""){//删除三材类别时,清空三材系数
+                value = null;
+                data.materialCoe = null;
+            }
+        }
+        if(dataCode == 'materialCoe'){
+            value = scMathUtil.roundForObj(value,getDecimal("material"));
+        }
+
+        data[dataCode] = value ;
+        updateMap[id] = data;
     },
     batchUpdateConsumption:function(changeInfo){
         let projectGLJ = projectObj.project.projectGLJ;

+ 16 - 7
web/building_saas/main/js/views/project_view.js

@@ -7,7 +7,7 @@ var projectObj = {
     mainSpread: null,
     mainController: null,
     gljSpreed:null,
-    beforeMainTreeSelectedChange: function (node) {
+    beforeMainTreeSelectedChange: function (pre) {
         /*if (node) {
             subViewObj.saveComments(node);
         }*/
@@ -32,8 +32,9 @@ var projectObj = {
         }
         project.mainTree.preSelected = node;
         projectObj.setNodesStyle(projectObj.mainController.sheet, refreshNodes);
-
-        subViewObj.loadComments(node);
+        if($('#linkComments').hasClass('active')){
+            subViewObj.loadComments(node);
+        }
         gljOprObj.showDataIfRationSelect(node);
         if (activeSubSheetIs(subSheetIndex.ssiCalcProgram)) {
             calcProgramObj.showData(node);
@@ -959,8 +960,10 @@ var projectObj = {
                          return project.Bills.isEngineerEst(project.mainTree.selected);//当焦点行是“专业工程暂估价”时,右键可见并有效。
                     },
                     callback: function () {
-                        projectObj.editContent(project.mainTree.selected,'engineeringContent');
-                        //BlockController.pasteBlock(project.mainTree.selected);
+                        let node = project.Bills.getNodeByFlag(project.mainTree.selected,fixedFlag.ENGINEERING_ESITIMATE);
+                        if(node){
+                            projectObj.editContent(node,'engineeringContent');
+                        }
                     }
                 },
                 "editService": {
@@ -970,7 +973,10 @@ var projectObj = {
                         return project.Bills.isTotalService(project.mainTree.selected);//当焦点行是“总承包服务费”时,右键可见并有效。
                     },
                     callback: function () {
-                        projectObj.editContent(project.mainTree.selected,'serviceContent');
+                        let node = project.Bills.getNodeByFlag(project.mainTree.selected,fixedFlag.TURN_KEY_CONTRACT);
+                        if(node){
+                            projectObj.editContent(node,'serviceContent');
+                        }
                     }
                 },
                 "editAccording": {
@@ -980,7 +986,10 @@ var projectObj = {
                         return project.Bills.isClaimVisa(project.mainTree.selected);//当焦点行是“签证及索赔计价”时,右键可见并有效。
                     },
                     callback: function () {
-                        projectObj.editContent(project.mainTree.selected,'claimVisa');
+                        let node = project.Bills.getNodeByFlag(project.mainTree.selected,fixedFlag.CLAIM_VISA);
+                        if(node){
+                            projectObj.editContent(node,'claimVisa');
+                        }
                     }
                 }
             }

+ 25 - 2
web/building_saas/main/js/views/sub_view.js

@@ -88,7 +88,6 @@ $("#linkZMHS").click(function(){        // 子目换算
     pageCCOprObj.active = false;
     refreshSubSpread();
 
-
     gljOprObj.activeTab='#linkZMHS';
 });
 
@@ -361,4 +360,28 @@ let subViewObj = {
     }
 }
 
-$("#linkComments").click(subViewObj.linkTabClick);
+$("#linkComments").click(subViewObj.linkTabClick);
+
+$('#linkGLJ').on('shown.bs.tab', function () {
+    gljOprObj.showDataIfRationSelect(projectObj.project.mainTree.selected, '111111');
+});
+
+$('#linkZMHS').on('shown.bs.tab', function (e) {
+    if(zmhs_obj.coeSpread == null || zmhs_obj.assSpread == null){
+        zmhs_obj.initSpread();
+    }
+    zmhs_obj.refresh();
+    zmhs_obj.showZMHSData();
+});
+
+$('#linkComments').on('shown.bs.tab', function () {
+    subViewObj.loadComments(projectObj.project.mainTree.selected);
+});
+
+$('#linkGCLMX').on('shown.bs.tab', function () {
+    gljOprObj.showDataIfRationSelect(projectObj.project.mainTree.selected, '111111');
+});
+
+$('#linkAZZJF').on('shown.bs.tab', function () {
+    gljOprObj.showDataIfRationSelect(projectObj.project.mainTree.selected, '111111');
+});

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

@@ -70,12 +70,16 @@ let zmhs_obj = {
 
     },
     showAssData:function (node) {
+        this.assSheet.suspendPaint();
+        this.assSheet.suspendEvent();
         let selected = node?node:projectObj.project.mainTree.selected;
         let assList = selected&&selected.data.rationAssList ? selected.data.rationAssList : [];
         this.assSheet.setRowCount(0);
         sheetCommonObj.showData(this.assSheet, this.assSetting, assList);
         this.assSheetData = assList;
         this.assSheet.getRange(assList.length,-1,this.assSheet.getRowCount()-assList.length, -1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+        this.assSheet.resumePaint();
+        this.assSheet.resumeEvent();
 
     },
     refresh:function () {
@@ -83,7 +87,7 @@ let zmhs_obj = {
         this.assSpread?this.assSpread.refresh():'';
     },
     showZMHSData:function (node) {
-        if(this.coeSpread&& this.assSpread){
+        if(this.coeSpread&& this.assSpread && $('#linkZMHS').hasClass('active')){
             this.showCoeData(node);
             this.showAssData(node);
             //hide floatingObject
@@ -381,14 +385,3 @@ let zmhs_obj = {
     }
 
 };
-
-
-$(function () {
-    $('#linkZMHS').on('shown.bs.tab', function (e) {
-        if(zmhs_obj.coeSpread == null || zmhs_obj.assSpread == null){
-            zmhs_obj.initSpread();
-        }
-        zmhs_obj.refresh();
-        zmhs_obj.showZMHSData();
-    })
-});

File diff suppressed because it is too large
+ 48 - 19
web/building_saas/pm/html/project-management.html


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

@@ -258,10 +258,14 @@ const projTreeObj = {
                     name: "分享",
                     icon: 'fa-share',
                     disabled: function () {
+                        let selectedItem = projTreeObj.tree.selected;
                         return true;
+                        // return !(selectedItem && selectedItem.data.projType === projectType.tender);
                     },
                     callback: function (key, opt) {
-
+                        $('#share-info').hide();
+                        $('#share').find('.card').hide();
+                        $('#share').modal('show');
                     }
                 },
             }
@@ -2814,4 +2818,54 @@ function refreshTenderFile(tenders, type, newName){
    });
 }
 
-//获取当前版本信息
+//添加分享
+$('#sharePhone').change(function () {
+    let phone = $(this).val();
+    let hintInfo = $('#share-info');
+    if(!phone || phone.trim() === ''){
+        replaceClass(hintInfo, 'text-info', 'text-danger');
+        setDangerInfo(hintInfo, '请输入手机号码。', true);
+        return;
+    }
+    //根据手机号获取用户
+    CommonAjax.post('/user/getUserByMobile', {mobile: phone}, function (rstData) {
+        if(!rstData){
+            replaceClass(hintInfo, 'text-info', 'text-danger');
+            setDangerInfo(hintInfo, '账号不存在。', true);
+        }
+        else{
+            console.log(rstData);
+            $('#user_name').text(rstData.real_name ? rstData.real_name : '');
+            $('#user_company').text(rstData.company ? rstData.company : '');
+            $('#user_mobile').text(rstData.mobile ? rstData.mobile : '');
+            $('#user_email').text(rstData.email ? rstData.email : '');
+            $('#share').find('.card').show();
+            //判断项目是否已经分享
+            //CommonAjax.post('/pm/api/getProjectShareInfo');
+        }
+    });
+});
+
+function shareTender(){
+    let phone = $('#sharePhone').val();
+    let hintInfo = $('#share-info');
+    if(!phone || phone.trim() === ''){
+        replaceClass(hintInfo, 'text-info', 'text-danger');
+        setDangerInfo(hintInfo, '请输入手机号码。', true);
+        return;
+    }
+    //根据手机号获取用户
+    CommonAjax.post('/user/getUserByMobile', {mobile: phone}, function (rstData) {
+        if(!rstData){
+            replaceClass(hintInfo, 'text-info', 'text-danger');
+            setDangerInfo(hintInfo, '账号不存在。', true);
+        }
+        else{
+            $('#user_name').text(rstData.real_name ? rstData.real_name : '');
+            $('#user_company').text(rstData.company ? rstData.company : '');
+            $('#user_mobile').text(rstData.mobile ? rstData.mobile : '');
+            $('#user_email').text(rstData.email ? rstData.email : '');
+            $('#share').find('.card').show();
+        }
+    });
+}