Explorar el Código

定额稳定土相关

zeweizhong hace 6 años
padre
commit
5fb28b758d

+ 1 - 0
config/gulpConfig.js

@@ -17,6 +17,7 @@ module.exports = {
         'lib/lodash/lodash.js',
         'public/web/commonAlert.js',
         'public/web/headerOpr.js',
+        'public/common_util.js',
         'lib/jquery-editable-select/jquery.editable-select.min.js'
     ],
     common_css:[

+ 10 - 0
modules/all_models/ration_glj.js

@@ -34,6 +34,16 @@ var ration_glj = new Schema({
     customQuantity:String,
     rationItemQuantity:String,
     tenderQuantity:String,//调整后消耗量
+    // 定额配合比
+    rationProportion: {
+        type: Number,
+        default: 0
+    },
+    // 调整配合比
+    adjustProportion: {
+        type: Number,
+        default: 0
+    },
     createType: {type: String,default:'normal'},//normal、add、replace  正常、添加工料机、替换工料机
     from:{type: String,default:'std'}//std, cpt  来自标准工料机库、补充工料机库
 },{versionKey:false});

+ 3 - 0
modules/main/facade/ration_facade.js

@@ -512,6 +512,7 @@ async function addRationGLJ(std,newRation,compilation,isMaterial,connect_key) {
         }
         for(let sub of std.rationGljList){
             let newGLJ = {};
+            let proportion = sub.proportion || 0;
             newGLJ.ID = uuidV1();
             newGLJ.projectID = newRation.projectID;
             newGLJ.GLJID = sub.gljId;
@@ -520,6 +521,8 @@ async function addRationGLJ(std,newRation,compilation,isMaterial,connect_key) {
             newGLJ.rationItemQuantity = sub.consumeAmt;
             newGLJ.quantity = sub.consumeAmt;
             newGLJ.glj_repository_id = std.rationRepId;
+            newGLJ.rationProportion = proportion;
+            newGLJ.adjustProportion = proportion;
             let std_glj = getStdGlj(sub,stdGLJMap,cptGLJMap,{},ext);
             if(std_glj){
                 ration_glj_facade.setPropertyFromStd(newGLJ,std_glj);

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

@@ -16,7 +16,8 @@ module.exports={
     mReplaceGLJ:mReplaceGLJ,
     updateRationGLJByEdit:updateRationGLJByEdit,
     getGLJClass:getGLJClass,
-    deleteRationGLJ:deleteRationGLJ
+    deleteRationGLJ:deleteRationGLJ,
+    updateProportion:updateProportion
 }
 function createRationGLJ() {
     let gls = mongoose.model('ration_glj');
@@ -117,6 +118,16 @@ async function deleteRationGLJ (req,res) {
     res.json(result);
 }
 
+async function updateProportion(req, res) {
+    try {
+        const data = JSON.parse(req.body.data);
+        const rst = await ration_glj_facade.updateProportion(data.proportionList, data.projectID, data.rationID);
+        res.json({ error: 0, data: rst, message: 'success' });
+    } catch (err) {
+        res.json({ error: 1, data: null, message: err.message });
+    }
+}
+
 async function replaceGLJ(req, res){
     let result={
         error:0

+ 77 - 61
modules/ration_glj/facade/glj_calculate_facade.js

@@ -16,20 +16,22 @@ let glj_type_util = require('../../../public/cache/std_glj_type_util');
 const scMathUtil = require('../../../public/scMathUtil').getUtil();
 let decimal_facade = require('../../main/facade/decimal_facade');
 let gljUtil = require('../../../public/gljUtil');
+const common_util = require('../../../public/common_util');
 
 module.exports={
     calculateQuantity:calculateQuantity,
     getGLJTypeByID:getGLJTypeByID
 }
-//辅助定额调整、替换工料机、标准附注条件调整、添加工料机、自定义消耗量(包括删除工料机)、自定义乘系数、市场单价调整
+//辅助定额调整、替换工料机、稳定土配合比、标准附注条件调整、添加工料机、自定义消耗量(包括删除工料机)、自定义乘系数、市场单价调整
 let stateSeq ={
     ass:1,
     replace:2,
-    coe:3,
-    add:4,
-    cusQuantity:5,
-    cusCoe:6,
-    adjMak:7
+    proportion: 3,
+    coe:4,
+    add:5,
+    cusQuantity:6,
+    cusCoe:7,
+    adjMak:8
 };
 //自定义乘系数与定额工料机类型映射表
 let coeTypeMap = {
@@ -44,66 +46,71 @@ let coeTypeMap = {
 
 async function calculateQuantity(query,noNeedCal=null,refreshRationName = false){
     try {
-         let  result ={
-             glj_result:[],
-             rationID:query.rationID
-         };
-         let impactRation = await ration.findOne({ID:query.rationID});
-         let gljList = await ration_glj.find(query);//{projectID:query.projectID,rationID:query.rationID}
-         let coeList = await ration_coe.find({rationID:query.rationID}).sort('seq').exec();
-         let assList=[], assRation = null, adjustState=[],mixRatioMap = {};
-         if(!impactRation){//如果定额不存在或者已删除,返回空
-             return null;
-         }
-         if(impactRation._doc.hasOwnProperty("rationAssList")&&impactRation.rationAssList.length>0){
-             prepareAss(impactRation.rationAssList);
-             let temTimes = [];
-             let thirdRationCodes=[];
-             for(let i=0;i<impactRation.rationAssList.length;i++){
-                 let times = calculateTimes(impactRation.rationAssList[i]);
-                 if(times!=0){
-                     let thirdRationCode = impactRation.rationAssList[i].thirdRationCode;
-                     if(thirdRationCode && thirdRationCode !=''){
-                         temTimes.push(times);
-                         thirdRationCodes.push(thirdRationCode)
-                     }
-                     assRation = await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:impactRation.rationAssList[i].assistCode});
-                     assList.push({times:times,assRation:assRation});
-                     adjustState.push({index:stateSeq.ass,content:impactRation.rationAssList[i].name+" "+impactRation.rationAssList[i].actualValue+" : +"+impactRation.rationAssList[i].assistCode+"x"+times});
-                 }
-             }
-             if(temTimes.length == 2 &&thirdRationCodes[0] == thirdRationCodes[1] ){ //说明有第三定额
-                 let times_t = temTimes[0] * temTimes[1];
-                 let tration =  await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:thirdRationCodes[0]});
-                 if(tration){
-                     assList.push({times:times_t,assRation:tration});
-                     adjustState.push({index:stateSeq.ass,content:"+"+thirdRationCodes[0]+"x"+times_t});
-                 }
-             }
-         }
-         for(let glj of gljList){//先把混凝土,砂浆,配合比有自定义消耗的挑出来
-             if(gljUtil.isConcreteType(glj.type)) await getMixRatioMap(glj,gljList,coeList,assList,mixRatioMap);
-         }
+        let  result ={
+            glj_result:[],
+            rationID:query.rationID
+        };
+        let impactRation = await ration.findOne({ID:query.rationID});
+        let gljList = await ration_glj.find(query);//{projectID:query.projectID,rationID:query.rationID}
+        let coeList = await ration_coe.find({rationID:query.rationID}).sort('seq').exec();
+        let assList=[], assRation = null, adjustState=[],mixRatioMap = {};
+        if(!impactRation){//如果定额不存在或者已删除,返回空
+            return null;
+        }
+        if(impactRation._doc.hasOwnProperty("rationAssList")&&impactRation.rationAssList.length>0){
+            prepareAss(impactRation.rationAssList);
+            let temTimes = [];
+            let thirdRationCodes=[];
+            for(let i=0;i<impactRation.rationAssList.length;i++){
+                let times = calculateTimes(impactRation.rationAssList[i]);
+                if(times!=0){
+                    let thirdRationCode = impactRation.rationAssList[i].thirdRationCode;
+                    if(thirdRationCode && thirdRationCode !=''){
+                        temTimes.push(times);
+                        thirdRationCodes.push(thirdRationCode)
+                    }
+                    assRation = await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:impactRation.rationAssList[i].assistCode});
+                    assList.push({times:times,assRation:assRation});
+                    adjustState.push({index:stateSeq.ass,content:impactRation.rationAssList[i].name+" "+impactRation.rationAssList[i].actualValue+" : +"+impactRation.rationAssList[i].assistCode+"x"+times});
+                }
+            }
+            if(temTimes.length == 2 &&thirdRationCodes[0] == thirdRationCodes[1] ){ //说明有第三定额
+                let times_t = temTimes[0] * temTimes[1];
+                let tration =  await  std_ration_lib_ration_items.findOne({rationRepId:impactRation.libID,code:thirdRationCodes[0]});
+                if(tration){
+                    assList.push({times:times_t,assRation:tration});
+                    adjustState.push({index:stateSeq.ass,content:"+"+thirdRationCodes[0]+"x"+times_t});
+                }
+            }
+        }
+        for(let glj of gljList){//先把混凝土,砂浆,配合比有自定义消耗的挑出来
+            if(gljUtil.isConcreteType(glj.type)) await getMixRatioMap(glj,gljList,coeList,assList,mixRatioMap);
+        }
         gljList = gljUtil.sortRationGLJ(gljList);
         for(let i =0;i<gljList.length;i++ ){
             let r = await calculateQuantityPerGLJ(gljList[i],gljList,coeList,assList,adjustState,mixRatioMap,noNeedCal);
             if(quantityUpdateCheck(gljList[i],r) == true) result.glj_result.push(r);
         }
-         if(noNeedCal==null && result.glj_result.length > 0){
-             await ration_glj.bulkWrite(generateUpdateTasks(result.glj_result));
-         }
-         adjustState= _.sortByOrder(adjustState, ['index'], ['asc']);
-         adjustState=_.map(adjustState, _.property('content'));
-         let adjustStateString = adjustState.join(';');
-         let setData = {adjustState:adjustStateString};
-         if(refreshRationName == true){//需要更新定额名称
-             let newName = generateRationName(impactRation,gljList);
-             setData.name = newName;
-             result.rationName = newName;
-         }
-         await ration.update({ID:query.rationID},setData);
-         result.adjustState=adjustStateString;
-         return result;
+        if(noNeedCal==null && result.glj_result.length > 0){
+            await ration_glj.bulkWrite(generateUpdateTasks(result.glj_result));
+        }
+        // 稳定土调整状态
+        const proportionStr = gljList.filter(glj => glj.rationProportion).map(glj => glj.adjustProportion || 0).join(':');
+        if (proportionStr) {
+            adjustState.push({ index: stateSeq.proportion, content: proportionStr });
+        }
+        adjustState= _.sortByOrder(adjustState, ['index'], ['asc']);
+        adjustState=_.map(adjustState, _.property('content'));
+        let adjustStateString = adjustState.join(';');
+        let setData = {adjustState:adjustStateString};
+        if(refreshRationName == true){//需要更新定额名称
+            let newName = generateRationName(impactRation,gljList);
+            setData.name = newName;
+            result.rationName = newName;
+        }
+        await ration.update({ID:query.rationID},setData);
+        result.adjustState=adjustStateString;
+        return result;
     }catch (err){
         console.log(err);
         throw err;
@@ -141,6 +148,11 @@ function generateRationName(ration,gljList) {
             caption =  caption.replace('%s',r);
         }
     }
+    // 更新定额名称中显示的稳定土配合比
+    const proportionStr = gljList.filter(glj => glj.rationProportion).map(glj => glj.adjustProportion || 0).join(':');
+    if (proportionStr) {
+        caption = caption.replace('%p', proportionStr);
+    }
     let reNameList = [];
     for(let g of gljList){
         //glj._doc.createType=='replace'&&glj.rcode!=glj.code
@@ -175,6 +187,10 @@ function generateUpdateTasks(result) {
 async function calcWhenNoCustomQuantiyt(decimal,glj,gljList,coeList,assList) {
     let quantity = glj.rationItemQuantity ? scMathUtil.roundTo(parseFloat(glj.rationItemQuantity),-decimal):0;
     quantity =scMathUtil.roundTo(await calculateAss(quantity,assList,glj),-decimal);
+    if (glj.rationProportion && common_util.isDef(glj.adjustProportion)) {
+        const proportionRate = glj.adjustProportion / glj.rationProportion;
+        quantity *= proportionRate;
+    }
     quantity = calculateQuantityByCoes(quantity,coeList,glj,gljList,decimal);
     return quantity;
 }

+ 29 - 1
modules/ration_glj/facade/ration_glj_facade.js

@@ -27,7 +27,8 @@ module.exports = {//先 exports再require 防止循环引用
     updateRationGLJFromDoc:updateRationGLJFromDoc,
     getGLJLibByEngineerID:getGLJLibByEngineerID,
     prepareExtData:prepareExtData,
-    setPropertyFromStd:setPropertyFromStd
+    setPropertyFromStd:setPropertyFromStd,
+    updateProportion: updateProportion
 };
 
 let mongoose = require('mongoose');
@@ -171,6 +172,8 @@ function createNewRecord(ration_glj) {
     newRecoed.rationItemQuantity = ration_glj.rationItemQuantity;
     newRecoed.customQuantity = ration_glj.customQuantity;
     newRecoed.quantity = ration_glj.quantity;
+    newRecoed.rationProportion = ration_glj.rationProportion;
+    newRecoed.adjustProportion = ration_glj.adjustProportion;
     newRecoed.name = ration_glj.name;
     newRecoed.code = ration_glj.code;
     newRecoed.original_code = ration_glj.original_code;
@@ -967,6 +970,31 @@ async function doRationGLJUpdate(data) {
     return resutl;
 }
 
+async function updateProportion(proportionList, projectID, rationID) {
+    const bulks = proportionList.map(item => {
+        return {
+            updateOne: {
+                filter: {ID: item.ID},
+                update: {$set: {adjustProportion: item.adjustProportion}}
+            }
+        }
+    });
+    if (bulks.length) {
+        await ration_glj.bulkWrite(bulks);
+    }
+    const calcRst = await glj_calculate_facade.calculateQuantity({ projectID, rationID }, null, true);
+    const rationGLJ = {
+        quantityRefresh: true,
+        glj_result: calcRst.glj_result
+    };
+    const ration = {
+        ID: calcRst.rationID,
+        adjustState: calcRst.adjustState,
+        name: calcRst.rationName
+    };
+    return { ration_glj: rationGLJ, ration, add:[], delete:[], replace: [] };
+}
+
 async function getGLJClass(info, data) {
     let result = {
         exist: false

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

@@ -16,6 +16,7 @@ module.exports = function (app) {
     rgRouter.post('/updateRationGLJByEdit',rgController.updateRationGLJByEdit);
     rgRouter.post('/getGLJClass/:engineerID', rgController.getGLJClass);
     rgRouter.post('/deleteRationGLJ', rgController.deleteRationGLJ);
+    rgRouter.post('/updateProportion', rgController.updateProportion);
 
     app.use('/rationGlj',rgRouter);
 }

+ 30 - 0
public/common_util.js

@@ -0,0 +1,30 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/11/12
+ * @version
+ */
+
+((factory) => {
+    if (typeof module !== 'undefined') {
+        module.exports = factory();
+    } else {
+        window._commonUtil = factory();
+    }
+})(() => {
+    function isDef(val) {
+        return typeof val !== 'undefined' && val !== null;
+    }
+    
+    function isEmptyVal(val) {
+        return val === null || val === undefined || val === '';
+    }
+
+    return {
+        isDef,
+        isEmptyVal
+    };
+});

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

@@ -242,6 +242,9 @@
                                                   <div class="tab-pane" id="rnc-fz">
                                                       <div class="main-data-bottom ovf-hidden" id="assSpread"></div>
                                                   </div>
+                                                  <div class="tab-pane" id="rnc-stable">
+                                                      <div class="main-data-bottom ovf-hidden" id="stableSpread"></div>
+                                                  </div>
                                               </div>
                                              <!-- <div class="p-0" id="openItemText" style="height:100%;width: 40px">
                                                   <div class="tn-nav d-flex align-items-start flex-column" data-toggle="tooltip" data-placement="left" title="" data-original-title="打开项目特征">
@@ -271,6 +274,7 @@
                                                           </li>-->
                                                           <li class="nav-item" data-toggle="tooltip" data-placement="left" title="附注条件"><a data-toggle="tab"  id="hs-nav" href="#rnc-zm" role="tab"class="zmhs-link nav-link">换算<!--<i class="fa fa-check-circle-o"></i>--></a></li>
                                                           <li class="nav-item" data-toggle="tooltip" data-placement="left" title="自定义系数"><a data-toggle="tab" href="#rnc-cus" role="tab"class="zmhs-link nav-link">系数<!--<i class="fa fa-wrench"></i>--></a></li>
+                                                          <li class="nav-item" data-toggle="tooltip" data-placement="left" title="定额稳定土"><a data-toggle="tab" href="#rnc-stable" role="tab" class="zmhs-link nav-link">稳定土</a></li>
                                                           <!--                     <li class="nav-item" data-toggle="tooltip" data-placement="left" title="增减换算"><a data-toggle="tab" href="#rnc-fz" role="tab"class="zmhs-link nav-link "><i class="fa fa-plus"></i></a></li>-->
                                                         <!--  <li class="nav-item"><a data-toggle="tab" href="#rnc-xm" role="tab"  class="nav-link">项目特征</a></li>
                                                           <li class="nav-item"><a data-toggle="tab" href="#rnc-zm" role="tab" class="nav-link">子目换算</a></li>

+ 23 - 0
web/building_saas/main/js/models/ration_glj.js

@@ -495,6 +495,7 @@ let ration_glj = {
                     gljOprObj.refreshView();
                     me.refreshTreeNodeIfNeeded(recode);//刷新造价书上的树节点(如果需要)
                     me.reCalcWhenGLJChange(recode);//触发计算定额以及父节点
+                    zmhs_obj.refreshStableDataIfNeeded();
                     $.bootstrapLoading.end();
                     installationFeeObj.calcInstallationFee();
                 });
@@ -1023,6 +1024,28 @@ let ration_glj = {
             }
             project.calcProgram.calcNodesAndSave(nodes);
         };
+        ration_glj.prototype.updateProportion = function (proportionList, projectID, rationID) {
+            const postData = {
+                proportionList,
+                projectID,
+                rationID
+            };
+            $.bootstrapLoading.start();
+            CommonAjax.post('/rationGLJ/updateProportion', postData, function (rst) {
+                proportionList.forEach(item => {
+                    const glj = zmhs_obj.stableSheetData.find(glj => glj.ID === item.ID);
+                    if (glj) {
+                        glj.adjustProportion = item.adjustProportion;
+                    }
+                });
+                zmhs_obj.refreshStableDataIfNeeded();
+                zmhs_obj.refreshAfterUpdate(rst);
+                $.bootstrapLoading.end();
+            }, function () {
+                zmhs_obj.refreshStableDataIfNeeded();
+                $.bootstrapLoading.end();
+            });
+        };
         return new ration_glj(project);
     }
 };

+ 3 - 1
web/building_saas/main/js/views/sub_view.js

@@ -282,7 +282,7 @@ function refreshSubSpread(){
     if(MaterialController.spread) MaterialController.spread.refresh();
     BillsElf.refreshWorkBook();
     //if($('#linkZMHS').hasClass('active')) zmhs_obj.refresh();
-    if($('#rnc-zm').is(':visible')|| $('#rnc-fz').is(':visible') || $('#rnc-cus')) zmhs_obj.refresh();
+    if($('#rnc-zm').is(':visible')|| $('#rnc-fz').is(':visible') || $('#rnc-cus') || $('#rnc-stable').is(':visible')) zmhs_obj.refresh();
     if($('#linkMBZM').hasClass('active')) mbzm_obj.refresh();
 }
 
@@ -404,6 +404,8 @@ $('.gljSubTab ul li a').on('shown.bs.tab', function () {
         zmhs_obj.initAssSpread();
     }else if(this.hash == "#rnc-cus"){
         zmhs_obj.initCusSpread();
+    }else if(this.hash == "#rnc-stable"){
+        zmhs_obj.initStableSpread();
     }
     zmhs_obj.refresh();
     zmhs_obj.showDatas();

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

@@ -70,6 +70,21 @@ let zmhs_obj = {
         },
         emptyRowHeader: true
     },
+    stableSpread:null,
+    stableSheet:null,
+    stableSheetData:null,
+    stableSetting:{
+        header: [
+            {headerName: "材料编号", headerWidth: 100, dataCode: "code", dataType: "String"},
+            {headerName: "材料名称", headerWidth: 100, dataCode: "name", dataType: "String"},
+            {headerName: "调整配合比", headerWidth: 80, dataCode: "adjustProportion", dataType: "String", hAlign: "right", validator:"number", precision: 2}
+        ],
+        view: {
+            lockColumns:["code", "name"],
+            rowHeaderWidth:25
+        },
+        emptyRowHeader: true
+    },
     initSpread:function () {
         this.initCoeSpread();
         this.initAssSpread();
@@ -115,6 +130,18 @@ let zmhs_obj = {
             SheetDataHelper.protectdSheet(this.assSheet);
         }
     },
+    initStableSpread:function () {
+        if(zmhs_obj.stableSpread == null){
+            this.stableSpread = SheetDataHelper.createNewSpread($("#stableSpread")[0]);
+            sheetCommonObj.spreadDefaultStyle(this.stableSpread);
+            this.stableSheet = this.stableSpread.getSheet(0);
+            sheetCommonObj.initSheet(this.stableSheet, this.stableSetting, 30);
+            this.stableSheet.name('ration_stable');
+            this.stableSheet.bind(GC.Spread.Sheets.Events.ValueChanged,this.onStableValueChange);
+            this.stableSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onStableRangeChanged);
+            SheetDataHelper.protectdSheet(this.stableSheet);
+        }
+    },
     showCoeData:function (node) {
         let preSelections = this.coeSheet.getSelections();
         let selected = node?node:projectObj.project.mainTree.selected;
@@ -170,7 +197,18 @@ let zmhs_obj = {
             disableSpread(zmhs_obj.cusSpread);
         }
     },
-
+    showStableData: function (node) {
+        // 过滤出定额配合比不为0的数据
+        const stableList = gljOprObj.sheetData.filter(glj => !glj.isMixRatio && glj.rationProportion);
+        this.stableSheetData = stableList;
+        sheetCommonObj.showData(this.stableSheet, this.stableSetting, stableList);
+        const proportionCol = this.stableSetting.header.findIndex(item => item.dataCode === 'adjustProportion');
+        this.stableSheet.getRange(0, proportionCol, stableList.length, 1, GC.Spread.Sheets.SheetArea.viewport).locked(false);
+        this.stableSheet.getRange(stableList.length, -1, this.stableSheet.getRowCount() - stableList.length, -1, GC.Spread.Sheets.SheetArea.viewport).locked(true);
+        if(projectReadOnly){
+            disableSpread(zmhs_obj.cusSpread);
+        }
+    },
     getComboBoxForCodes:function (coe,i) {
         this.coeSheet.getCell(i, 1, GC.Spread.Sheets.SheetArea.viewport).locked(false);
         let options = coe.option_list; //coe.option_codes.split("|");
@@ -261,12 +299,19 @@ let zmhs_obj = {
         $('#coeSpread').is(':visible')&&this.coeSpread?this.coeSpread.refresh():'';
         $('#cusSpread').is(':visible')&&this.cusSpread?this.cusSpread.refresh():'';
         $('#assSpread').is(':visible')&&this.assSpread?this.assSpread.refresh():'';
+        $('#stableSpread').is(':visible')&&this.stableSpread?this.stableSpread.refresh():'';
     },
     showDatas:function () {
         if($('#itemCharacterText').is(':visible'))MaterialController.showItemCharacterText()
         if($('#coeSpread').is(':visible')) this.showCoeData();
         if($('#cusSpread').is(':visible')) this.showCusData();
         if($('#assSpread').is(':visible')) this.showAssData();
+        if($('#stableSpread').is(':visible')) this.showStableData();
+    },
+    refreshStableDataIfNeeded: function () {
+        if ($('#stableSpread').is(':visible')) {
+            this.showStableData();
+        }
     },
     showZMHSData:function (node) {
         if(this.coeSpread&& this.assSpread && $('#linkZMHS').hasClass('active')){
@@ -554,6 +599,90 @@ let zmhs_obj = {
         }
         return true;
     },
+    onStableValueChange: function (e, args) {
+        const changeData = [{ row: args.row, col: args.col, value: args.newValue }];
+        zmhs_obj.changeStableValue(changeData);
+    },
+    onStableRangeChanged: function (e, args) {
+        const changeData = args.changedCells.map(cell => {
+            const value = args.sheet.getValue(cell.row, cell.col);
+            return { row: cell.row, col: cell.col, value};
+        });
+        zmhs_obj.changeStableValue(changeData);
+    },
+    changeStableValue: function (data) {
+        const isValid = data.every(cell => _commonUtil.isDef(cell.value) && sheetCommonObj.checkData(cell.col, this.stableSetting, cell.value));
+        if (!isValid) {
+            this.showDatas();
+            alert('输入的数据类型不对,请重新输入!');
+            return;
+        }
+        const precision = this.stableSetting.header.find(item => item.dataCode === 'adjustProportion').precision;
+        this.handleDataWithPrecision(data, precision);
+        const sheetData = this.getAutoStableSheetData(data, precision);
+        // 获取需要更新的数据
+        const rationGLJ = projectObj.project.ration_glj;
+        const updateProportionList = this.getStablePostData(sheetData);
+        const projectID = projectObj.project.ID();
+        const rationID = projectObj.project.mainTree.selected.data.ID;
+        rationGLJ.updateProportion(updateProportionList, projectID, rationID);
+    },
+    // 将值进行四舍五入处理
+    handleDataWithPrecision: function (data, precision) {
+        data.forEach(cell => {
+            cell.value = scMathUtil.roundTo(cell.value, -precision);
+        });
+    },
+    // 获取经过自动处理后的表格数据
+    getAutoStableSheetData: function (changedData, precision) {
+        const expectedValue = 100;
+        const unchangedData = [];
+        const col = this.stableSetting.header.findIndex(item => item.dataCode === 'adjustProportion');
+        this.stableSheetData.forEach((item, index) => {
+            const matchData = changedData.find(dItem => dItem.row === index);
+            if (!matchData) {
+                unchangedData.push({ row: index, col: col, value: item.adjustProportion});
+            }
+        });
+        // 稳定土各项调整配合比总值必须为100,不为100则自动调整某一项
+        const allData = _.sortBy(changedData.concat(unchangedData), 'row');
+        const total = allData.reduce((acc, cur) => scMathUtil.roundTo(acc + cur.value, -precision), 0);
+        if (total === expectedValue) {
+            return allData;
+        }
+        const autoAdjustData = getAutoAdjustData(changedData, unchangedData);
+        // 排除自动调整行后的总值
+        const exclusionTotal = allData.reduce((acc, cur) =>
+            cur.row !== autoAdjustData.row
+                ? scMathUtil.roundTo(acc + cur.value, -precision)
+                : acc + 0 , 0);
+        const autoAdjustValue = scMathUtil.roundTo(expectedValue - exclusionTotal, -precision);
+        autoAdjustData.value = autoAdjustValue;
+        return allData;
+        // 获取自动调整行数据
+        function getAutoAdjustData(changedData, unchangedData) {
+            debugger;
+            const changedMaxData = changedData[changedData.length - 1];
+            // 如果不存在不变的数据,自动调整行号为:最大变化数据行
+            if (!unchangedData.length) {
+                return changedMaxData;
+            }
+            const unchangedMinData = unchangedData[0];
+            // 如果存在不变的数据,则自动调整配合比的行数据为:比最大变化数据行大的行,或最小未变数据行
+            const greaterData = unchangedData.find(item => item.row > changedMaxData.row);
+            return greaterData ? greaterData : unchangedMinData;
+        }
+    },
+    getStablePostData: function (sheetData) {
+        const postData = [];
+        sheetData.forEach(cell => {
+            const originItem = this.stableSheetData[cell.row];
+            if (cell.value !== originItem.adjustProportion) {
+                postData.push({ ID: originItem.ID, adjustProportion: cell.value});
+            }
+        });
+        return postData;
+    },
     getSideResize: function () {
         let zmhs_sideResizeEles = {};
         zmhs_sideResizeEles.eleObj = {

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

@@ -280,5 +280,6 @@
 <script type="text/javascript" src="/lib/lodash/lodash.js"></script>
 <script type="text/javascript" src="/public/web/commonAlert.js"></script>
 <script type="text/javascript" src="/public/web/headerOpr.js"></script>
+<script type="text/javascript" src="/public/common_util.js"></script>
 <script type="text/javascript" src="/lib/jquery-editable-select/jquery.editable-select.min.js"></script>
 <!-- endinject -->