浏览代码

提交配合比相关修改(包括删除、修改单价等)

caiaolin 8 年之前
父节点
当前提交
b869700372

+ 6 - 2
modules/common/const/glj_type_const.js

@@ -23,8 +23,12 @@ const gljType = {
     // 商品砂浆
     COMMERCIAL_MORTAR: 206,
     // ==============材料类型=================
-    // 机械
-    MACHINE: 3,
+    // ==============机械类型=================
+    // 普通机械
+    GENERAL_MACHINE: 301,
+    // 机械组成物
+    MACHINE_COMPOSITION: 302,
+    // ==============机械类型=================
     // 主材
     MAIN_MATERIAL: 4,
     // 设备

+ 2 - 0
modules/common/std/schemas/std_mix_ratio.js

@@ -23,6 +23,8 @@ let modelSchema = {
     },
     // 对应的工料机总库id
     glj_id: Number,
+    // 对应工料机类型
+    glj_type: Number
 };
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 export {model as default, collectionName as collectionName};

+ 45 - 8
modules/glj/controllers/glj_controller.js

@@ -51,10 +51,11 @@ class GLJController extends BaseController {
 
             // 先获取对应标段的项目工料机数据
             let gljListModel = new GLJListModel();
-            let gljList = await gljListModel.getListByProjectId(projectId, unitPriceFileId);
+            let [gljList, mixRatioConnectData] = await gljListModel.getListByProjectId(projectId, unitPriceFileId);
 
             let renderData = {
                 gljList: JSON.stringify(gljList),
+                mixRatioConnectData: JSON.stringify(mixRatioConnectData),
                 materialIdList: gljListModel.materialIdList,
                 ownCompositionTypes: gljListModel.ownCompositionTypes,
                 hostname: request.hostname,
@@ -110,11 +111,14 @@ class GLJController extends BaseController {
                     model = new GLJListModel();
                     // 更新数据
                     result = await model.updateById(id, updateData);
+
                     break;
                 case 'unit_price':
+                    let extend = request.body.extend;
                     model = new UnitPriceModel();
                     // 更新数据
-                    result = await model.updatePrice({id: id}, updateData);
+                    result = await model.updatePrice({id: id}, updateData, extend);
+
                     break;
                 case 'mix_ratio':
                     let marketPrice = request.body.market_price;
@@ -175,6 +179,7 @@ class GLJController extends BaseController {
             if (!unitPriceFile) {
                 throw '没有对应的单价文件';
             }
+
             // 单价文件id作为同步的roomId
             let unitPriceFileId = unitPriceFile.id;
 
@@ -194,6 +199,38 @@ class GLJController extends BaseController {
     }
 
     /**
+     * 删除配合比数据
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async deleteMixRatio(request, response) {
+        let id = request.body.id;
+        id = parseInt(id);
+        let responseData = {
+            err: 0,
+            msg: ''
+        };
+        try {
+            if (isNaN(id) || id <= 0) {
+                throw '参数错误';
+            }
+
+            let mixRatioModel = new MixRatioModel();
+            let result = await mixRatioModel.deleteById(id);
+            if (!result) {
+                throw '删除失败';
+            }
+        } catch (error) {
+            responseData.err = 1;
+            responseData.msg = error;
+        }
+
+        response.json(responseData);
+    }
+
+    /**
      * 模拟定额插入
      *
      * @param {object} request
@@ -203,15 +240,15 @@ class GLJController extends BaseController {
     async test(request, response) {
         // 从定额库获取的数据
         let data = {
-            glj_id: 801,
+            glj_id: 802,
             project_id: 1,
-            code: '81040102',
-            name: 'C15特细砂干硬性混凝土',
-            specs: 'C15',
+            code: '80010101',
+            name: 'C20特细砂干硬性混凝土',
+            specs: 'C20',
             unit: 'm³',
             type: GLJTypeConst.CONCRETE,
-            base_price: 323.25,
-            market_price: 323.25
+            base_price: 423.36,
+            market_price: 423.36
         };
         try {
             let gljListModel = new GLJListModel();

+ 27 - 7
modules/glj/models/glj_list_model.js

@@ -73,6 +73,7 @@ class GLJListModel extends BaseModel {
      */
     async getListByProjectId(projectId, unitPriceFileId) {
         let gljData = null;
+        let mixRatioConnectData = {};
         try {
             // 首先获取对应标段下所有的项目工料机数据
             let condition = {project_id: projectId};
@@ -114,6 +115,7 @@ class GLJListModel extends BaseModel {
 
             // 查找组成物的消耗量
             let totalComposition = {};
+            let mixRatioData = {};
             if (projectGLJCode.length > 0) {
                 let mixRatioModel = new MixRatioModel();
                 condition = {connect_code: {"$in": projectGLJCode}, unit_price_file_id: unitPriceFileId};
@@ -122,11 +124,23 @@ class GLJListModel extends BaseModel {
                     totalComposition[tmp.connect_code] = totalComposition[tmp.connect_code] === undefined ? tmp.consumption :
                         totalComposition[tmp.connect_code] + tmp.consumption;
                     totalComposition[tmp.connect_code] = Number(totalComposition[tmp.connect_code].toFixed(2));
+
+                    if (mixRatioData[tmp.glj_id] !== undefined) {
+                        mixRatioData[tmp.glj_id].push(tmp);
+                    } else {
+                        mixRatioData[tmp.glj_id] = [tmp];
+                    }
+
+                    if (mixRatioConnectData[tmp.glj_id] !== undefined) {
+                        mixRatioConnectData[tmp.glj_id].push(tmp.connect_code);
+                    } else {
+                        mixRatioConnectData[tmp.glj_id] = [tmp.connect_code];
+                    }
                 }
             }
 
             // 组合单价数据
-            this.combineData(gljData, unitPriceList, quantityList, [], totalComposition);
+            this.combineData(gljData, unitPriceList, quantityList, mixRatioData, totalComposition);
 
             // 排序
             gljData.sort(function (a, b) {
@@ -137,7 +151,7 @@ class GLJListModel extends BaseModel {
             gljData = [];
         }
 
-        return gljData;
+        return [gljData, mixRatioConnectData];
     }
 
     /**
@@ -168,8 +182,10 @@ class GLJListModel extends BaseModel {
 
             // 组成物消耗量
             let gljId = glj.glj_id + '';
-            glj.consumption = mixRatioData[gljId] !== undefined ? mixRatioData[gljId].consumption : 0;
-            glj.mix_ratio_id = mixRatioData[gljId] !== undefined ? mixRatioData[gljId].id : 0;
+            // glj.consumption = mixRatioData[gljId] !== undefined ? mixRatioData[gljId].consumption : 0;
+            // glj.mix_ratio_id = mixRatioData[gljId] !== undefined ? mixRatioData[gljId].id : 0;
+            // glj.connect_code = mixRatioData[gljId] !== undefined ? mixRatioData[gljId].connect_code : '';
+            glj.ratio_data = mixRatioData[gljId] !== undefined ? mixRatioData[gljId] : [];
 
             // 计算调整基价
             switch (glj.unit_price.type + '') {
@@ -385,6 +401,7 @@ class GLJListModel extends BaseModel {
         // 查找对应组成物的项目工料机数据
         let [projectGljList, compositionList] = await this.getCompositionGLJList(code, projectId, 'name');
 
+
         // 整理配合比待插入数据
         let mixRatioInsertData = [];
         for (let tmp of compositionList) {
@@ -393,7 +410,8 @@ class GLJListModel extends BaseModel {
                 consumption: tmp.consumption,
                 glj_id: tmp.glj_id,
                 unit_price_file_id: unitPriceFileId,
-                connect_code: tmp.connect_code
+                connect_code: tmp.connect_code,
+                glj_type: tmp.glj_type
             };
             mixRatioInsertData.push(mixRatioData);
         }
@@ -461,7 +479,7 @@ class GLJListModel extends BaseModel {
                 unit: tmp.unit,
                 unit_price_file_id: unitPriceFileId,
                 // 如果没有对应的工料机类型则默认设置为普通材料
-                type: gljType[tmp.unit] !== undefined ? gljType[tmp.unit] : GLJTypeConst.MAIN_MATERIAL
+                type: gljType[tmp.gljDistType] !== undefined ? gljType[tmp.gljDistType] : GLJTypeConst.GENERAL_MATERIAL
             };
             unitPriceInsertData.push(unitPriceData);
 
@@ -496,7 +514,9 @@ class GLJListModel extends BaseModel {
             // 查找对应的项目工料机数据
             let projectGLJData = await this.getDataById(projectGLJId);
 
-            let allowType = [GLJTypeConst.MIX_RATIO, GLJTypeConst.CONCRETE, GLJTypeConst.MORTAR];
+            let allowType = [GLJTypeConst.MIX_RATIO, GLJTypeConst.CONCRETE, GLJTypeConst.MORTAR,
+                GLJTypeConst.GENERAL_MACHINE];
+            console
             if (projectGLJData.unit_price === null || allowType.indexOf(projectGLJData.unit_price.type) < 0) {
                 throw '找不到相关项目工料机';
             }

+ 4 - 1
modules/glj/models/schemas/glj.js

@@ -70,7 +70,10 @@ let modelSchema = {
     // 显示组成物的消耗量
     consumption: Number,
     // 显示关联配合比的id
-    mix_ratio_id: Number
+    mix_ratio_id: Number,
+    // 显示关联父级工料机code(组合物用)
+    connect_code: String,
+    ratio_data: Schema.Types.Mixed
 };
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false}));
 

+ 1 - 0
modules/glj/models/schemas/mix_ratio.js

@@ -29,6 +29,7 @@ let modelSchema = {
         type: String,
         index: true
     },
+    glj_type: Number
 };
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 export {model as default, collectionName as collectionName};

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

@@ -170,9 +170,10 @@ class UnitPriceModel extends BaseModel {
      *
      * @param {Object} condition
      * @param {Object} updateData
+     * @param {String} extend
      * @return {Promise}
      */
-    async updatePrice(condition, updateData) {
+    async updatePrice(condition, updateData, extend = '') {
         if (Object.keys(condition).length <= 0 || Object.keys(updateData).length <= 0) {
             return false;
         }
@@ -191,6 +192,24 @@ class UnitPriceModel extends BaseModel {
                 break;
         }
 
+        // 额外更新数据
+        if (extend !== '') {
+            extend = JSON.parse(extend);
+            for (let code in extend) {
+                let extendUpdateData = {
+                    market_price: extend[code].market_price,
+                };
+                let tmpCondition = {
+                    unit_price_file_id: unitPriceData.unit_price_file_id,
+                    code: code
+                };
+                let extendResult = await this.db.update(tmpCondition, extendUpdateData);
+                if (!extendResult) {
+                    throw '更新额外数据,编码为' + code + '的数据失败!';
+                }
+            }
+        }
+
         let result = await this.db.update(condition, updateData);
         return result.ok !== undefined && result.ok === 1;
     }

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

@@ -15,6 +15,7 @@ let gljController = new GLJController();
 router.get('/', gljController.init, gljController.index);
 router.post('/update', gljController.init, gljController.updateData);
 router.post('/get-ratio', gljController.init, gljController.getMixRatio);
+router.post('/delete-ratio', gljController.init, gljController.deleteMixRatio);
 
 router.get('/test', gljController.init, gljController.test);
 router.get('/testModify', gljController.init, gljController.testModify);

+ 12 - 10
web/glj/html/glj_index.html

@@ -1,4 +1,5 @@
 <%include header.html %>
+<link rel="stylesheet" href="/lib/jquery-contextmenu/jquery.contextMenu.css">
 <div class="main">
     <div class="main-nav">
         <ul class="nav flex-column">
@@ -34,7 +35,7 @@
                                 <a class="nav-link" data-toggle="tab" data-name="mix-ratio" href="#ph" role="tab">配合比表</a>
                             </li>
                             <li class="nav-item">
-                                <a class="nav-link" data-toggle="tab" data-name="" href="#jx" role="tab">机械单价</a>
+                                <a class="nav-link" data-toggle="tab" data-name="machine" href="#jx" role="tab">机械单价</a>
                             </li>
                         </ul>
                         <!-- Tab panes -->
@@ -49,12 +50,7 @@
                                 </div>
                             </div>
                             <div class="tab-pane" id="jx" role="tabpanel">
-                                <div class="main-data-bottom">
-                                    <table class="table table-sm table-bordered m-0">
-                                        <thead>
-                                        <tr><th></th><th>编码</th><th>名称</th><th>单位</th><th>基价单价</th><th>调整基价</th><th>用量</th></tr>
-                                        </thead>
-                                    </table>
+                                <div class="main-data-bottom" id="machine">
                                 </div>
                             </div>
                         </div>
@@ -66,6 +62,9 @@
 </div>
 <script type="text/javascript">
     let jsonData = '<%- gljList %>';
+    let mixRatioConnectData = '<%- mixRatioConnectData %>';
+    mixRatioConnectData = JSON.parse(mixRatioConnectData);
+
     let materialIdList = '<%- materialIdList %>';
     materialIdList = materialIdList !== '' ? materialIdList.split(",") : '';
     let host = '<%= hostname %>';
@@ -76,12 +75,15 @@
     GLJTypeConst = JSON.parse(GLJTypeConst);
 
     // 混凝土、砂浆、配合比、机械 市场单价不能修改
-    let canNotChangeTypeId = '<- ownCompositionTypes %>';
+    let canNotChangeTypeId = '<%- ownCompositionTypes %>';
     canNotChangeTypeId = canNotChangeTypeId !== '' ? canNotChangeTypeId.split(",") : '';
-
 </script>
 <%include footer.html %>
+<script type="text/javascript" src="/lib/jquery-contextmenu/jquery.contextMenu.js"></script>
+<script type="text/javascript" src="/public/web/sheet/sheet_data_helper.js"></script>
+<script type="text/javascript" src="/public/web/number_util.js"></script>
 <script type="text/javascript" src="/web/glj/js/socket.js"></script>
 <script type="text/javascript" src="/web/glj/js/spread_common.js"></script>
 <script type="text/javascript" src="/web/glj/js/glj_index.js"></script>
-<script type="text/javascript" src="/web/glj/js/mix_ratio.js"></script>
+<script type="text/javascript" src="/web/glj/js/mix_ratio.js"></script>
+<script type="text/javascript" src="/web/glj/js/machine.js"></script>

+ 166 - 19
web/glj/js/glj_index.js

@@ -10,7 +10,8 @@ let gljSheet = null;
 let sourceData = [];
 let spread = null;
 let isChanging = false;
-let gljActiveRowIndex = 0;
+let firstMixRatioRow = -1;
+let firstMachineRow = -1;
 $(document).ready(function () {
 
     // 初始化表格
@@ -21,13 +22,12 @@ $(document).ready(function () {
         $("#notify").slideUp('fast');
         if (changeInfo.length > 0) {
             for (let index in changeInfo) {
-                let cell = sheet.getCell(changeInfo[index].row, changeInfo[index].col, GC.Spread.Sheets.SheetArea.viewport);
+                let cell = gljSheet.getCell(changeInfo[index].row, changeInfo[index].col, GC.Spread.Sheets.SheetArea.viewport);
                 cell.value(changeInfo[index].newValue);
             }
         }
         changeInfo = [];
     });
-
 });
 
 /**
@@ -53,6 +53,10 @@ function initGLJExcel() {
         {name: '送达地点', field: 'delivery_address', visible: true},
         {name: '不调价', field: 'is_adjust_price', visible: true, cellType: new GC.Spread.Sheets.CellTypes.CheckBox(),  validator: 'boolean'},
         {name: 'UID', field: 'unit_price.id', visible: false},
+        {name: '工料机ID', field: 'glj_id', visible: false},
+        {name: '组成物消耗量', field: 'consumption', visible: false},
+        {name: '父级关联编码', field: 'connect_code', visible: false},
+        {name: '消耗量', field: 'ratio_data', visible: false},
     ];
     // 数据转换格式
     sourceData = JSON.parse(jsonData);
@@ -115,7 +119,7 @@ function initGLJExcel() {
         let type = gljSheet.getValue(row, typeColumn);
 
         // 如果类型为混凝土、砂浆、配合比、机械,则提示
-        if (field === 'unit_price.market_price' && canNotChangeTypeId.indexOf(type) >= 0) {
+        if (field === 'unit_price.market_price' && canNotChangeTypeId.indexOf(type + '') >= 0) {
             alert('当前工料机的市场单价由组成物计算得出,不可直接修改');
         }
     });
@@ -129,6 +133,7 @@ function initGLJExcel() {
         }
 
     });
+
 }
 
 /**
@@ -171,6 +176,8 @@ function specialColumn(sourceData) {
     let isEvaluateColumn = getFieldColumn(header, 'is_evaluate');
     // 获取市场单价列号
     let marketPriceColumn = getFieldColumn(header, 'unit_price.market_price');
+    let connectCodeColumn = getFieldColumn(header, 'connect_code');
+    let consumptionColumn = getFieldColumn(header, 'consumption');
     for(let data of sourceData) {
         // 只有材料才显示是否暂估
         if (materialIdList.indexOf(data.unit_price.type + '') < 0) {
@@ -180,15 +187,126 @@ function specialColumn(sourceData) {
             gljSheet.getRange(rowCounter, isEvaluateColumn, 1, 1).locked(true);
             gljSheet.setValue(rowCounter, isEvaluateColumn, '');
         }
+
         // 如果类型为混凝土、砂浆、配合比、机械,则市场单价不能修改
-        if (canNotChangeTypeId.indexOf(data.unit_price.type) >= 0) {
+        if (canNotChangeTypeId.indexOf(data.unit_price.type + '') >= 0) {
+            firstMixRatioRow = firstMixRatioRow === -1 && data.unit_price.type !== GLJTypeConst.GENERAL_MACHINE ?
+                rowCounter : firstMixRatioRow;
+            firstMachineRow = firstMachineRow === -1 && data.unit_price.type === GLJTypeConst.GENERAL_MACHINE ?
+                rowCounter : firstMachineRow;
             // 锁定该单元格
             gljSheet.getRange(rowCounter, marketPriceColumn, 1, 1).locked(true);
         }
+        // 处理数据
+        if (data.ratio_data.length > 0) {
+            let connectCode = [];
+            let consumption = [];
+            for (let tmp of data.ratio_data) {
+                connectCode.push(tmp.connect_code);
+                consumption.push(tmp.consumption);
+            }
+            let connectCodeString = connectCode.join(',');
+            let consumptionString = consumption.join(',');
+            gljSheet.setValue(rowCounter, connectCodeColumn, connectCodeString);
+            gljSheet.setValue(rowCounter, consumptionColumn, consumptionString);
+        }
         rowCounter++;
     }
 }
 
+/**
+ * 组成物父级价格计算
+ *
+ * @param {Number} row
+ * @return {Object}
+ */
+function compositionParentCalculate(row) {
+    // 获取关联编码
+    let connectCodeColumn = getFieldColumn(header, 'connect_code');
+    let activeConnectCode = gljSheet.getValue(row, connectCodeColumn);
+
+    // 不属于组成物则忽略
+    if (activeConnectCode === '' || activeConnectCode === undefined) {
+        return null;
+    }
+    activeConnectCode = activeConnectCode.split(',');
+
+    // 计算同级组成物的价格
+    // 遍历所有记录
+    let maxRow = gljSheet.getRowCount();
+    let consumptionColumn = getFieldColumn(header, 'consumption');
+    let marketPriceColumn = getFieldColumn(header, 'unit_price.market_price');
+    let parentMarketPrice = {};
+    for (let i = 0; i < maxRow; i++) {
+        let connectCode = gljSheet.getValue(i, connectCodeColumn);
+        if (connectCode === null) {
+            continue;
+        }
+        connectCode = connectCode.split(',');
+        // 消耗量
+        let consumption = gljSheet.getValue(i, consumptionColumn);
+        consumption = consumption.split(',');
+
+        // 获取市场价
+        let marketPrice = gljSheet.getValue(i, marketPriceColumn);
+
+        for (let active of activeConnectCode) {
+            let index = connectCode.indexOf(active);
+            if (index < 0) {
+                continue;
+            }
+            let rowConsumption = consumption[index] === undefined ? 0 : consumption[index];
+            // 计算价格
+            let rowMarketPrice = (marketPrice * rowConsumption).toDecimal(2);
+            parentMarketPrice[active] = parentMarketPrice[active] === undefined ?
+                rowMarketPrice : (parentMarketPrice[active] + rowMarketPrice).toDecimal(2);
+
+        }
+
+    }
+
+    return parentMarketPrice;
+}
+
+/**
+ * 组成物父类数据更新
+ *
+ * @param {Object} parentMarketPrice
+ * @return {void}
+ */
+function compositionParentUpdate(parentMarketPrice) {
+    let marketPriceColumn = getFieldColumn(header, 'unit_price.market_price');
+    // 定位到父节点,然后更新
+    for (let code in parentMarketPrice) {
+        let changeRow = searchKeyword(code);
+        gljSheet.setValue(changeRow, marketPriceColumn, parentMarketPrice[code]);
+    }
+
+}
+
+/**
+ * 查找指定数据并返回行号
+ *
+ * @param {String} keyword
+ * @param {Number} rowStart
+ * @param {Number} columnStart
+ * @return {Number}
+ */
+function searchKeyword(keyword, rowStart = 0, columnStart = 0) {
+    let condition = new GC.Spread.Sheets.Search.SearchCondition();
+    condition.searchString = keyword;
+    condition.startSheetIndex = 0;
+    condition.endSheetIndex = 0;
+    condition.searchFlags = GC.Spread.Sheets.Search.SearchFlags.ignoreCase | GC.Spread.Sheets.Search.SearchFlags.blockRange;
+    condition.searchOrder = GC.Spread.Sheets.Search.SearchOrder.nOrder;
+    condition.searchTarget = GC.Spread.Sheets.Search.SearchFoundFlags.cellText;
+    condition.sheetArea = GC.Spread.Sheets.SheetArea.viewport;
+    condition.rowStart = rowStart;
+    condition.columnStart = columnStart;
+
+    let result = spread.search(condition);
+    return result.foundRowIndex;
+}
 
 /**
  * 基价单价计算
@@ -222,7 +340,7 @@ function adjustPriceCalculate(type, info) {
         // 材料、主材、设备 调整基价=基价单价
         case GLJTypeConst.MAIN_MATERIAL:
         case GLJTypeConst.EQUIPMENT:
-            let basePrice = sheet.getValue(info.row, basePriceColumn);
+            let basePrice = gljSheet.getValue(info.row, basePriceColumn);
             gljSheet.setValue(info.row, adjustPriceColumn, basePrice);
             break;
 
@@ -238,11 +356,11 @@ function adjustPriceCalculate(type, info) {
  */
 function marketPriceCalculate(type, info) {
     switch (type) {
-        // 人工、材料(普通材料)触发 需计算混凝土、砂浆、配合比、机械的市场单价 @todo 后续添加
+        // 人工、材料(普通材料)触发 需计算混凝土、砂浆、配合比、机械的市场单价
         case GLJTypeConst.LABOUR:
         case GLJTypeConst.GENERAL_MATERIAL:
             // 计算
-            console.log('触发计算');
+            compositionParentUpdate(info.parentMarketPrice);
             break;
     }
 }
@@ -253,15 +371,28 @@ function marketPriceCalculate(type, info) {
  * @param {Array} typeList
  * @return {void}
  */
-function filterDataByType(type) {
-    sourceData = [];
-    let testData = JSON.parse(jsonData);
-    for(let tmp of testData) {
-        if (type.indexOf(tmp.unit_price.type) >= 0) {
-            sourceData.push(tmp);
-        }
+function filterDataByType(typeList) {
+    let typeColumn = getFieldColumn(header, 'unit_price.type');
+    typeColumn = parseInt(typeColumn);
+    let filter = new GC.Spread.Sheets.Filter.HideRowFilter(new GC.Spread.Sheets.Range(-1, typeColumn, -1, 1));
+    gljSheet.rowFilter(filter);
+    filter.filterButtonVisible(false);
+
+    for (let type of typeList) {
+        let condition = new GC.Spread.Sheets.ConditionalFormatting.Condition(GC.Spread.Sheets.ConditionalFormatting.ConditionType.numberCondition, {
+            compareType: GC.Spread.Sheets.ConditionalFormatting.GeneralComparisonOperators.equalsTo,
+            expected: type
+        });
+
+        filter.addFilterItem(typeColumn, condition);
     }
-    gljSheet.setDataSource(sourceData);
+
+    filter.filter(typeColumn);
+    gljSheet.invalidateLayout();
+    gljSheet.repaint();
+    let filterRow = typeList.indexOf(GLJTypeConst.GENERAL_MACHINE) >= 0 ? firstMachineRow : firstMixRatioRow;
+    // 筛选后选中第一个符合类型的单元格
+    gljSheet.setSelection(filterRow, 0, 1, 1);
 }
 
 /**
@@ -306,10 +437,22 @@ function updateBindEvent(element, info) {
     }
     let id = gljSheet.getValue(row, idColumn);
 
+    // 直接在前端计算后传值后台改
+    let extend = {};
+    let parentMarketPrice = compositionParentCalculate(row);
+    if (Object.keys(parentMarketPrice).length > 0) {
+        for (let activeCode in parentMarketPrice) {
+            let tmpObject = {
+                market_price: parentMarketPrice[activeCode],
+            };
+            extend[activeCode] = tmpObject;
+        }
+    }
+    extend = Object.keys(extend).length > 0 ?  JSON.stringify(extend) : '';
     $.ajax({
         url: '/glj/update',
         type: 'post',
-        data: {id: id, field: field, value: value},
+        data: {id: id, field: field, value: value, extend: extend},
         dataType: 'json',
         error: function() {
             alert('数据传输有误!');
@@ -326,6 +469,9 @@ function updateBindEvent(element, info) {
                 alert('更改数据失败!');
             } else {
                 // 成功则触发相应事件
+                if (parentMarketPrice !== null) {
+                    info.parentMarketPrice = parentMarketPrice;
+                }
                 successTrigger(field, info);
             }
         }
@@ -340,6 +486,7 @@ function updateBindEvent(element, info) {
  */
 function getActiveProjectGLJId() {
     let activeGLJRow = gljSheet.getActiveRowIndex();
+
     // 获取当前行的工料机id
     let gljIdColumn = getFieldColumn(header, 'id');
     let gljId = gljSheet.getValue(activeGLJRow, gljIdColumn);
@@ -357,7 +504,7 @@ function setGLJQuantity(row, change) {
     let quantityColumn = getFieldColumn(header, 'quantity');
     let oldValue = gljSheet.getValue(row, quantityColumn);
 
-    change = Number((oldValue + change).toFixed(2));
+    change = (oldValue + change).toDecimal(2);
     gljSheet.setValue(row, quantityColumn, change);
 }
 
@@ -374,7 +521,7 @@ function setGLJCellByField(row, field, value, appendMode) {
     let columnIndex = getFieldColumn(header, field);
     if (appendMode) {
         let oldValue = gljSheet.getValue(row, columnIndex);
-        value = Number((oldValue + value).toFixed(2));
+        value = (oldValue + value).toDecimal(2);
     }
     gljSheet.setValue(row, columnIndex, value);
 }

+ 147 - 49
web/glj/js/mix_ratio.js

@@ -9,22 +9,27 @@ let mixRatioHeader = [];
 let mixRatioSheet = null;
 let mixRatioSpread = null;
 let currentTag = '';
+let mixRatioRightClickTarget = null;
+let isDeleting = false;
 $(document).ready(function() {
 
     initMixRatioExcel();
 
+    // 初始化右键相关
+    initMixRatioRightClick();
     // 切换tab触发refresh
     $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
         currentTag = $(e.target).data('name');
+
+        // 获取工料机当前选中的行号
+        let projectGLJId = 0;
         if (currentTag === "mix-ratio" && mixRatioSpread !== null) {
             // 筛选数据显示(显示混凝土、砂浆、配合比)
             filterDataByType([GLJTypeConst.CONCRETE, GLJTypeConst.MORTAR, GLJTypeConst.MIX_RATIO]);
-
-            // 获取工料机当前选中的行号
-            let projectGLJId = getActiveProjectGLJId();
+            projectGLJId = getActiveProjectGLJId();
 
             // 获取数据
-            getMixRatioData(projectGLJId);
+            getRatioData(projectGLJId, getMixRatio);
         }
     });
 
@@ -93,30 +98,123 @@ function initMixRatioExcel() {
 }
 
 /**
- * 根据项目工料机id获取对应的配合比数据
+ * 设置特殊单元格数据
  *
- * @param {Number} projectGLJid
+ * @param {object} sourceData
  * @return {void}
  */
-function getMixRatioData(projectGLJid) {
+function ratioSpecialColumn(sourceData) {
+    let rowCounter = 0;
+    // 获取市场单价列号
+    let consumptionColumn = getFieldColumn(mixRatioHeader, 'consumption');
+    let idColumn = getFieldColumn(mixRatioHeader, 'mix_ratio_id');
+    for(let data of sourceData) {
+        // 把消耗量从对象中抽离出来
+        if (data.ratio_data.consumption !== undefined) {
+            mixRatioSheet.setValue(rowCounter, consumptionColumn, data.ratio_data.consumption);
+            mixRatioSheet.setValue(rowCounter, idColumn, data.ratio_data.id);
+        }
+        rowCounter++;
+    }
+}
+
+
+/**
+ * 初始化右键
+ *
+ * @return {void}
+ */
+function initMixRatioRightClick() {
+    $.contextMenu({
+        selector: '#mix-ratio',
+        build: function ($trigger, e) {
+            mixRatioRightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, mixRatioSpread);
+            return mixRatioRightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport ||
+                mixRatioRightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+        },
+        items: {
+            "deleteMixRatio": {
+                name: "删除",
+                icon: 'fa-trash-o',
+                disabled: function () {
+                    return mixRatioRightClickTarget.row === undefined;
+                },
+                callback: function (key, opt) {
+                    let row = mixRatioRightClickTarget.row;
+                    let idColumn = getFieldColumn(mixRatioHeader, 'mix_ratio_id');
+                    let deleteId = mixRatioSheet.getValue(row, idColumn);
+                    deleteMixRatio(deleteId, row);
+                }
+            },
+        }
+    });
+}
+
+/**
+ * 获取对应的配合比方法
+ *
+ * @param {Object} response
+ * @param {String} type
+ * @return {void|boolean}
+ */
+function getMixRatio(response, type) {
+    switch (type) {
+        case 'success':
+            response.data = JSON.parse(response.data);
+            // 设置数据
+            mixRatioSheet.setDataSource(response.data);
+            ratioSpecialColumn(response.data);
+            mixRatioSpread.refresh();
+            break;
+        case 'fail':
+            mixRatioSheet.setDataSource(null);
+            mixRatioSpread.refresh();
+            alert('不存在对应数据');
+            break;
+    }
+}
+
+/**
+ * 删除配合比数据
+ *
+ * @param {Number} id
+ * @param {Number} row
+ * @return {void | boolean}
+ */
+function deleteMixRatio(id, row) {
+    id = parseInt(id);
+    if (isNaN(id) || id <= 0) {
+        alert('参数错误!');
+    }
+    if (isDeleting) {
+        return false;
+    }
+    // 获取当前行的消耗量
+    let consumptionColumn = getFieldColumn(mixRatioHeader, 'consumption');
+    let consumption = mixRatioSheet.getValue(row, consumptionColumn);
     $.ajax({
-        url: '/glj/get-ratio',
+        url: '/glj/delete-ratio',
         type: 'post',
-        data: {id: projectGLJid, project_id: 1},
+        data: {id: id},
+        dataType: 'json',
         error: function() {
-            alert('服务器有误');
+            isDeleting = false;
+            alert('服务器繁忙');
         },
         beforeSend: function() {
-
+            isDeleting = true;
         },
         success: function(response) {
             if (response.err === 0) {
-                response.data = JSON.parse(response.data);
-                // 设置数据
-                mixRatioSheet.setDataSource(response.data);
-                mixRatioSpread.refresh();
-            } else {
-                alert('获取失败');
+                // 删除成功后重新计算父工料机相关信息
+                let [parentMarketPrice, parentBasePrice] = getBaseAndMarketPrice('delete', row);
+                let info = {
+                    parentMarketPrice: parentMarketPrice,
+                    parentBasePrice: parentBasePrice,
+                    change: -consumption
+                };
+                mixRatioSheet.setValue(row, consumptionColumn, 0);
+                mixRatioSuccess('', info);
             }
         }
     });
@@ -158,29 +256,7 @@ function updateConsumption(element, info) {
     }
     let id = mixRatioSheet.getValue(row, idColumn);
 
-    // 计算父级3个价格
-    let maxRow = mixRatioSheet.getRowCount();
-    // 获取对应列的列号
-    let marketPriceColumn = getFieldColumn(mixRatioHeader, 'unit_price.market_price');
-    let consumptionColumn = getFieldColumn(mixRatioHeader, 'consumption');
-    let basePriceColumn = getFieldColumn(mixRatioHeader, 'unit_price.base_price');
-
-    let parentMarketPrice = 0;
-    let parentBasePrice = 0;
-    for(let i = 0; i < maxRow; i++) {
-        // 获取市场单价
-        let marketPrice = mixRatioSheet.getValue(i, marketPriceColumn);
-        // 获取基价单价
-        let basePrice = mixRatioSheet.getValue(i, basePriceColumn);
-        // 获取消耗量(如果是当前修改的行则替换数据)
-        let consumption = row === i ? info.newValue : mixRatioSheet.getValue(i, consumptionColumn);
-
-        parentMarketPrice += consumption * marketPrice;
-        parentBasePrice += consumption * basePrice;
-    }
-    parentMarketPrice = Number(parentMarketPrice.toFixed(2));
-    parentBasePrice = Number(parentBasePrice.toFixed(2));
-
+    let [parentMarketPrice, parentBasePrice] = getBaseAndMarketPrice('modify', row, info.newValue);
     $.ajax({
         url: '/glj/update',
         type: 'post',
@@ -201,6 +277,9 @@ function updateConsumption(element, info) {
                 mixRatioSheet.setValue(row, column, info.oldValue);
                 alert('更改数据失败!');
             } else {
+                info.parentMarketPrice = parentMarketPrice;
+                info.parentBasePrice = parentBasePrice;
+                info.change = info.newValue - info.oldValue;
                 mixRatioSuccess(field, info);
             }
         }
@@ -216,9 +295,23 @@ function updateConsumption(element, info) {
 function mixRatioSuccess(field, info) {
     // 成功则对相应的总消耗量进行设置
     let activeGLJRow = gljSheet.getActiveRowIndex();
-    let change = Number((info.newValue - info.oldValue).toFixed(2));
-    setGLJCellByField(activeGLJRow, 'quantity', change, true);
+    setGLJCellByField(activeGLJRow, 'quantity', info.change, true);
+
+    // 设置父级3个价格
+    setGLJCellByField(activeGLJRow, 'unit_price.market_price', info.parentMarketPrice, false);
+    setGLJCellByField(activeGLJRow, 'unit_price.base_price', info.parentBasePrice, false);
+    setGLJCellByField(activeGLJRow, 'adjust_price', info.parentBasePrice, false);
+}
 
+/**
+ * 计算市场单价基价单价
+ *
+ * @param {String} scene
+ * @param {Number} affectRow
+ * @param {Number} newValue
+ * @return {Array}
+ */
+function getBaseAndMarketPrice(scene, affectRow, newValue = 0) {
     // 计算父级3个价格
     let maxRow = mixRatioSheet.getRowCount();
     // 获取对应列的列号
@@ -233,15 +326,20 @@ function mixRatioSuccess(field, info) {
         let marketPrice = mixRatioSheet.getValue(i, marketPriceColumn);
         // 获取基价单价
         let basePrice = mixRatioSheet.getValue(i, basePriceColumn);
-        // 获取消耗量
-        let consumption = mixRatioSheet.getValue(i, consumptionColumn);
+
+        // 如果是删除则忽略即将被删除的行数据
+        if (scene === 'delete' && affectRow === i) {
+            continue;
+        }
+
+        // 获取消耗量(如果是当前修改的行则替换数据)
+        let consumption = i === affectRow ? newValue : mixRatioSheet.getValue(i, consumptionColumn);
 
         parentMarketPrice += consumption * marketPrice;
         parentBasePrice += consumption * basePrice;
     }
-    parentMarketPrice = Number(parentMarketPrice.toFixed(2));
-    parentBasePrice = Number(parentBasePrice.toFixed(2));
-    setGLJCellByField(activeGLJRow, 'unit_price.market_price', parentMarketPrice, false);
-    setGLJCellByField(activeGLJRow, 'unit_price.base_price', parentBasePrice, false);
-    setGLJCellByField(activeGLJRow, 'adjust_price', parentBasePrice, false);
+
+    parentMarketPrice = parentMarketPrice.toDecimal(2);
+    parentBasePrice = parentBasePrice.toDecimal(2);
+    return [parentMarketPrice, parentBasePrice]
 }

+ 33 - 0
web/glj/js/spread_common.js

@@ -62,4 +62,37 @@ function getStyle(setting) {
     style.locked = setting.readOnly === undefined ? true : setting.readOnly;
     style.hAlign = setting.hAlign === undefined ? GC.Spread.Sheets.HorizontalAlign.center : setting.hAlign;
     return style;
+}
+
+/**
+ * 根据项目工料机id获取对应的配合比或者机械单价数据
+ *
+ * @param {Number} projectGLJid
+ * @param {function} callback
+ * @return {void|boolean}
+ */
+function getRatioData(projectGLJid, callback) {
+    projectGLJid = parseInt(projectGLJid);
+    if (isNaN(projectGLJid) || projectGLJid <= 0) {
+        callback(null, 'fail');
+        return false;
+    }
+    $.ajax({
+        url: '/glj/get-ratio',
+        type: 'post',
+        data: {id: projectGLJid, project_id: 1},
+        error: function() {
+            callback(null, 'fail');
+        },
+        beforeSend: function() {
+
+        },
+        success: function(response) {
+            if (response.err === 0) {
+                callback(response, 'success');
+            } else {
+                callback(null, 'fail');
+            }
+        }
+    });
 }