Bläddra i källkod

材料调差部分功能

laiguoran 5 år sedan
förälder
incheckning
0fcc99fec2

+ 46 - 2
app/controller/material_controller.js

@@ -243,7 +243,8 @@ module.exports = app => {
                 // 取所有工料表
                 renderData.materialBillsData = await ctx.service.materialBills.getAllDataByCondition({ where: { tid: ctx.tender.id } });
                 // 取所有已被调用的工料清单表
-                renderData.materialListData = await ctx.service.materialList.getAllDataByCondition({ where: { tid: ctx.tender.id } });
+                renderData.materialListData = await ctx.service.materialList.getMaterialData(ctx.tender.id);
+                renderData.materialNotJoinListData = await ctx.service.materialListNotjoin.getAllDataByCondition({ where: { tid: ctx.tender.id, mid: ctx.material.id } });
                 renderData.materialType = JSON.stringify(materialConst);
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.material.list);
                 // 获取清单数据
@@ -252,7 +253,7 @@ module.exports = app => {
                 // 获取所选期数据并合并相加同类清单项
                 renderData.curLedgerData = await ctx.service.stageBills.getStagesData(ctx.tender.id, ctx.material.stage_id);
                 renderData.curPosData = await ctx.service.stagePos.getStagesData(ctx.tender.id, ctx.material.stage_id);
-                await this.layout('material/list.ejs', renderData);
+                await this.layout('material/list.ejs', renderData, 'material/list_modal.ejs');
             } catch (err) {
                 this.log(err);
                 ctx.redirect('/tender/' + ctx.tender.id + '/measure/material');
@@ -260,6 +261,49 @@ module.exports = app => {
         }
 
         /**
+         * 调差清单 - 工料操作 (Ajax)
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async saveListsData(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                const responseData = {
+                    err: 0,
+                    msg: '',
+                    data: {},
+                };
+                switch (data.type) {
+                    case 'add':
+                        responseData.data = await ctx.service.materialList.add(data.postData);
+                        break;
+                    case 'del':
+                        await ctx.service.materialList.del(data.id);
+                        break;
+                    case 'update':
+                        if (data.updateData.quantity === '' || data.updateData.quantity === null) {
+                            throw '请输入数量';
+                        }
+                        // 判断数量是否为数字
+                        if (isNaN(data.updateData.quantity)) {
+                            throw '不能输入其它非数字类型字符';
+                        }
+                        await ctx.service.materialList.save(data.updateData);
+                        break;
+                    case 'useOther':
+                        responseData.data = await ctx.service.materialList.addOther(data.postData);
+                        break;
+                    default: throw '参数有误';
+                }
+
+                ctx.body = responseData;
+            } catch (err) {
+                this.log(err);
+                ctx.body = { err: 1, msg: err.toString(), data: null };
+            }
+        }
+
+        /**
          * 调差工料 - 编辑工料项 (Ajax)
          * @param ctx
          * @returns {Promise<void>}

+ 2 - 2
app/public/js/material.js

@@ -27,7 +27,7 @@ $(document).ready(() => {
             {title: '调差类型', colSpan: '1', rowSpan: '2', field: 't_type', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.isEdit', cellType: 'customizeCombo', comboItems: materialType.t_type, cellTypeKey: 1},
             {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 60, formatter: '@', readOnly: 'readOnly.isEdit'},
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@', readOnly: 'readOnly.isEdit'},
-            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 0, width: 60, formatter: '@', readOnly: 'readOnly.isEdit'},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: 'readOnly.isEdit'},
             {title: '规格', colSpan: '1', rowSpan: '2', field: 'spec', hAlign: 0, width: 230, formatter: '@', readOnly: 'readOnly.isEdit'},
             {title: '工料分类', colSpan: '1', rowSpan: '2', field: 'm_type', hAlign: 0, width: 60, readOnly: 'readOnly.isEdit', cellType: 'customizeCombo', comboItems: materialType.m_type, cellTypeKey: 2},
             {title: '本期应耗数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 100, type: 'Number', readOnly: 'readOnly.isEdit'},
@@ -54,7 +54,7 @@ $(document).ready(() => {
     const materialBase = {
         isEdit: function (data) {
             return materialListData.find(function (item) {
-                return item.mbid === data.id;
+                return item.mb_id === data.id;
             });
         }
     }

+ 316 - 33
app/public/js/material_list.js

@@ -20,7 +20,7 @@ $(document).ready(() => {
             {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 120, type: 'Number'},
             {title: '本期计量数量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 120, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 120, type: 'Number'},
-            {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'total_qty', hAlign: 2, width: 120, type: 'Number', getValue: 'getValue.qty'},
+            {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'gather_qty', hAlign: 2, width: 120, type: 'Number'},
         ],
         emptyRows: 0,
         headRows: 2,
@@ -30,28 +30,28 @@ $(document).ready(() => {
         readOnly: true,
         font: '10pt 微软雅黑',
     };
-
-    const ledgerCol = {
-        getValue: {
-            qty: function (data) {
-                return ZhCalc.add(data.contract_qty, data.qc_qty);
-            }
-        }
-    };
     // 解析清单汇总数据
     gclGatherModel.loadLedgerData(ledger, curLedgerData);
     gclGatherModel.loadPosData(pos, curPosData);
     const gclGatherData = gclGatherModel.gatherGclData();
+    console.log(gclGatherData);
     // 获取项目节数据
     function loadLeafXmjData(iGclRow) {
         const gcl = gclGatherData[iGclRow];
         if (gcl) {
             SpreadJsObj.loadSheetData(leafXmjSpread.getActiveSheet(), SpreadJsObj.DataType.Data, gcl.leafXmjs);
+            // 对清单调差工料table的单位数量进行改变
+            // console.log(materialSpreadSetting.cols[materialSpreadSetting.cols.length - 1]);
+            // materialSpreadSetting.cols[materialSpreadSetting.cols.length - 1].title = '|' + gcl.unit + '数量<a href="" data-toggle="tooltip" data-placement="bottom" title="单位数量:每一单位清单下所需工料消耗量。"><i class="fa fa-question-circle-o"></i></a>';
+            materialSpreadSetting.cols[materialSpreadSetting.cols.length - 1].title = '|' + gcl.unit + '数量';
+            // const sheet = materialSpread.getActiveSheet();
+            // sheet.setCellType(2,3, '1', spreadNS.SheetArea.colHeader);
+            SpreadJsObj.initSheet(materialSpread.getActiveSheet(), materialSpreadSetting);
+            // materialSpread.resumePaint();
         } else {
             SpreadJsObj.loadSheetData(leafXmjSpread.getActiveSheet(), SpreadJsObj.DataType.Data, []);
         }
     }
-    SpreadJsObj.initSpreadSettingEvents(ledgerSpreadSetting, ledgerCol);
     SpreadJsObj.initSheet(ledgerSpread.getActiveSheet(), ledgerSpreadSetting);
 
     // 项目明细table
@@ -67,7 +67,7 @@ $(document).ready(() => {
             {title: '|分项工程', colSpan: '|1', rowSpan: '|1', field: 'fxgc', hAlign: 0, width: 180, formatter: '@'},
             {title: '本期计量数量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},
-            {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'total_qty', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.qty'},
+            {title: '|小计', colSpan: '|1', rowSpan: '|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '本期价差', colSpan: '1', rowSpan: '2', field: 'jijia', hAlign: 2, width: 80, type: 'Number'},
         ],
         emptyRows: 0,
@@ -78,50 +78,333 @@ $(document).ready(() => {
         readOnly: true,
         font: '10pt 微软雅黑',
     };
-    const leafXmjCol = {
-        getValue: {
-            qty: function (data) {
-                return ZhCalc.add(data.contract_qty, data.qc_qty);
-            }
-        }
-    };
-    SpreadJsObj.initSpreadSettingEvents(leafXmjSpreadSetting, leafXmjCol);
     SpreadJsObj.initSheet(leafXmjSpread.getActiveSheet(), leafXmjSpreadSetting);
     // 加载清单数据
     SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Data, gclGatherData);
-    loadLeafXmjData(0);
-    SpreadJsObj.forbiddenSpreadContextMenu('#ledger-spread', ledgerSpread);
 
     // 调差清单工料table
     const materialSpread = SpreadJsObj.createNewSpread($('#material-spread')[0]);
     const materialSpreadSetting = {
         cols: [
-            {title: '清单调差工料|编号', colSpan: '4|1', rowSpan: '1|1', field: 'code', hAlign: 0, width: 80, formatter: '@'},
-            {title: '|名称', colSpan: '|1', rowSpan: '|1', field: 'name', hAlign: 0, width: 100, formatter: '@'},
-            {title: '|单位', colSpan: '|1', rowSpan: '|1', field: 'unit', hAlign: 1, width: 60, formatter: '@'},
-            {title: '|kg数量', colSpan: '1', rowSpan: '|1', field: 'num', hAlign: 2, width: 60, type: 'Number'},
+            {title: '清单调差工料|编号', colSpan: '4|1', rowSpan: '1|1', field: 'code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
+            {title: '|名称', colSpan: '|1', rowSpan: '|1', field: 'name', hAlign: 0, width: 100, formatter: '@', readOnly: true},
+            {title: '|单位', colSpan: '|1', rowSpan: '|1', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true},
+            {title: '|数量', colSpan: '1', rowSpan: '|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number', readOnly: readOnly.quantity},
         ],
         emptyRows: 0,
         headRows: 2,
         headRowHeight: [32, 32],
         defaultRowHeight: 30,
         headerFont: '10pt 微软雅黑',
-        readOnly: true,
         font: '10pt 微软雅黑',
     };
-    SpreadJsObj.initSheet(materialSpread.getActiveSheet(), materialSpreadSetting);
 
+    const materialCol = {
+        readOnly: {
+            quantity: function () {
+                const sheet = leafXmjSpread.getActiveSheet();
+                const select = SpreadJsObj.getSelectObject(sheet);
+                const notx = notJoinList.find(function (item) {
+                    return item.gcl_id === select.gcl_id && item.xmj_id === select.id && (select.mx_id === undefined || (select.mx_id !== undefined && select.mx_id === item.mx_id));
+                });
+                console.log(notx);
+                return readOnly || notx === undefined;
+            },
+        },
+    };
+    SpreadJsObj.initSpreadSettingEvents(materialSpreadSetting, materialCol);
+    // SpreadJsObj.initSheet(materialSpread.getActiveSheet(), materialSpreadSetting);
+    // 获取第一个调差工料数据
+    // 获取项目节数据
+    let materialList = [];
+    function loadMaterialData(iGclRow, iLXmjRow) {
+        const gcl = gclGatherData[iGclRow];
+        if (gcl && gcl.leafXmjs[iLXmjRow]) {
+            const xmj = gcl.leafXmjs[iLXmjRow];
+            materialList = [];
+            for (const m of materialListData) {
+                if (m.gcl_id === xmj.gcl_id && m.xmj_id === xmj.id && ((xmj.mx_id !==undefined && m.mx_id === xmj.mx_id) || xmj.mx_id === undefined)) {
+                    materialList.push(m);
+                }
+            }
+            console.log(materialList);
+            SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, materialList);
+        } else {
+            SpreadJsObj.loadSheetData(materialSpread.getActiveSheet(), SpreadJsObj.DataType.Data, []);
+        }
+    }
+
+    loadLeafXmjData(0);
+    loadMaterialData(0, 0);
+    // 不参与调差数据值变灰
+    function checkNotJoinMaterialData() {
+        const sheet = ledgerSpread.getActiveSheet();
+        const select = SpreadJsObj.getSelectObject(sheet);
+        const index = gclGatherData.indexOf(select);
+        if (index !== -1) {
+            const xmj = gclGatherData[index].leafXmjs;
+            const leafXmjSheet = leafXmjSpread.getActiveSheet();
+            for (const [iRow,x] of xmj.entries()) {
+                const notx = notJoinList.find(function (item) {
+                    return item.gcl_id === x.gcl_id && item.xmj_id === x.id && (x.mx_id === undefined || (x.mx_id !== undefined && x.mx_id === item.mx_id));
+                });
+                const color = notx === undefined ? '' : '#d6d8db';
+                leafXmjSheet.getRange(iRow, -1, 1, -1).backColor(color);
+            }
+        }
+    }
+    checkNotJoinMaterialData();
+    // 对添加工料表格赋值
+    function changeMaterialTable() {
+        $('#materialBills tr').removeClass('table-secondary');
+        $('#materialBills').find('input').removeAttr('disabled');
+        $('#materialBills').find('input').prop('checked', false);
+        for (const [index, ml] of materialList.entries()) {
+            const mbIndex = materialBillsData.findIndex(function (item) {
+                return item.id === ml.mb_id;
+            });
+            if (mbIndex !== -1) {
+                $('#materialBills tr').eq(mbIndex).addClass('table-secondary');
+                $('#materialBills').find('input').eq(mbIndex).attr('disabled', true);
+                $('#materialBills').find('input').eq(mbIndex).prop('checked', true);
+            }
+        }
+    }
+    // 添加调差工料
+    $('#add_material_bill').click(function () {
+        // 获取已选工料
+        $('#materialBills').find('input:disabled').prop('checked', false);
+        const selectList = $('#materialBills').find('input:checked');
+        if (selectList.length === 0) {
+            toastr.warning('请选择调差工料');
+            $('#materialBills').find('input:disabled').prop('checked', true);
+            return false;
+        }
+        const mb_id = [];
+        for (let s = 0; s < selectList.length; s++) {
+            mb_id.push($('#materialBills').find('input:checked').eq(s).val());
+        }
+        // 获取当前项目节或部位明细id
+        const sheet = ledgerSpread.getActiveSheet();
+        const select = SpreadJsObj.getSelectObject(sheet);
+        const index = gclGatherData.indexOf(select);
+        const leafXmjSheet = leafXmjSpread.getActiveSheet();
+        const leafXmjSelect = SpreadJsObj.getSelectObject(leafXmjSheet);
+        const gcl = gclGatherData[index].leafXmjs;
+        const leafXmjIndex = gcl.indexOf(leafXmjSelect);
+        const xmj = gcl[leafXmjIndex];
+        const data = {
+            xmj_id: xmj.id,
+            gcl_id: xmj.gcl_id,
+            mx_id: xmj.mx_id !== undefined ? xmj.mx_id : '',
+            mb_id: mb_id,
+        };
+        // 上传到数据库
+        postData(window.location.pathname + '/save', {type: 'add', postData: data}, function (result) {
+            // 添加到materialList里
+            materialListData = result;
+            loadMaterialData(index, leafXmjIndex);
+            $('#addgl').modal('hide');
+        });
+        $('#materialBills').find('input:disabled').prop('checked', true);
+    });
     if (!readOnly) {
-    } else {
-        SpreadJsObj.forbiddenSpreadContextMenu('#leaf-xmj-spread', leafXmjSpread);
-        SpreadJsObj.forbiddenSpreadContextMenu('#material-spread', materialSpread);
+        // leafXmj右键功能
+        $.contextMenu({
+            selector: '#leaf-xmj-spread',
+            build: function ($trigger, e) {
+                const target = SpreadJsObj.safeRightClickSelection($trigger, e, leafXmjSpread);
+                return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                'stop': {
+                    name: '不参与调差',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        const sheet = ledgerSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        const index = gclGatherData.indexOf(select);
+                        const leafXmjSheet = leafXmjSpread.getActiveSheet();
+                        const leafXmjSelect = SpreadJsObj.getSelectObject(leafXmjSheet);
+                        const iRow = gclGatherData[index].leafXmjs.indexOf(leafXmjSelect);
+                        leafXmjSheet.getRange(iRow, -1, 1, -1).backColor('#d6d8db');
+                    },
+                    disabled: function (key, opt) {
+                        const sheet = leafXmjSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        const notx = notJoinList.find(function (item) {
+                            return item.gcl_id === select.gcl_id && item.xmj_id === select.id && (select.mx_id === undefined || (select.mx_id !== undefined && select.mx_id === item.mx_id));
+                        });
+                        if (!readOnly && select && notx === undefined) {
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                },
+            }
+        });
+        const materialBase = {
+            isEdit: function (data) {
+                return materialListData.find(function (item) {
+                    return item.mbid === data.id;
+                });
+            }
+        };
+        // material-spread右键功能
+        const materialSpreadObj = {
+            del: function () {
+                const sheet = materialSpread.getActiveSheet();
+                const select = SpreadJsObj.getSelectObject(sheet);
+                console.log(select);
+                postData(window.location.pathname + '/save', {type: 'del', id: select.id}, function (result) {
+                    const index = materialList.indexOf(select);
+                    materialList.splice(index, 1);
+                    sheet.deleteRows(index, 1);
+                    SpreadJsObj.reLoadSheetData(materialSpread.getActiveSheet());
+                    const sel = sheet.getSelections();
+                    sheet.setSelection(index > 0 ? index - 1 : 0, sel.length > 0 ? sel[0].col : 0, 1, 1);
+                    const materialListIndex = materialListData.indexOf(select);
+                    materialListData.splice(materialListIndex, 1);
+                });
+            },
+            editEnded: function (e, info) {
+                if (info.sheet.zh_setting) {
+                    const select = SpreadJsObj.getSelectObject(info.sheet);
+                    const col = info.sheet.zh_setting.cols[info.col];
+                    // 未改变值则不提交
+                    const validText = info.editingText ? (typeof(info.editingText) === 'String' ? info.editingText.replace('\n', '') : info.editingText) : null;
+                    const orgValue = select[col.field];
+                    if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                        return;
+                    }
+                    // 更新至服务器
+                    postData(window.location.pathname + '/save', { type:'update', updateData: { id:select.id, quantity: validText } }, function (result) {
+                        const materialListIndex = materialListData.indexOf(select);
+                        const index = materialList.indexOf(select);
+                        select[col.field] = validText;
+                        materialListData.splice(materialListIndex, 1, select);
+                        materialList.indexOf(index, 1, select);
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    }, function () {
+                        SpreadJsObj.reLoadRowData(info.sheet, info.row);
+                    });
+                }
+            },
+            setReadOnly: function(readOnly) {
+                SpreadJsObj.resetFieldReadOnly(materialSpread.getActiveSheet(), 'quantity', readOnly);
+            }
+        };
+        materialSpread.bind(spreadNS.Events.EditEnded, materialSpreadObj.editEnded);
+        // 应用调差工料至其他清单明细
+        $('#user_all_material').click(function () {
+            const sheet = materialSpread.getActiveSheet();
+            const select = SpreadJsObj.getSelectObject(sheet);
+            if (select === undefined) {
+                toastr.warning('请选中需要应用到其他清单明细的调差工料');
+                return false;
+            }
+            const ledgerSheet = ledgerSpread.getActiveSheet();
+            const ledgerSelect = SpreadJsObj.getSelectObject(ledgerSheet);
+            if (ledgerSelect.leafXmjs.length < 2) {
+                toastr.warning('没有需要应用调差工料的其它清单明细');
+                return false;
+            }
+            // 判断需要应用调差工料的清单明细
+            const needAddList = [];
+            for (const xmj of ledgerSelect.leafXmjs) {
+                if (xmj.mx_id !== undefined) {
+                    const ml = materialListData.find(function (item) {
+                        return xmj.mx_id === item.mx_id && select.mb_id === item.mb_id;
+                    });
+                    if (ml === undefined) {
+                        needAddList.push(xmj.mx_id);
+                    }
+                }
+            }
+            if (needAddList.length === 0) {
+                toastr.warning('没有需要应用调差工料的其它清单明细');
+                return false;
+            }
+            // 更新至服务器
+            postData(window.location.pathname + '/save', { type:'useOther', postData: { mx_id: needAddList, select: select  } }, function (result) {
+                materialListData = result;
+                toastr.success('成功添加了' + needAddList.length + '条调差工料到其他清单明细中');
+            });
+        });
+        $.contextMenu({
+            selector: '#material-spread',
+            build: function ($trigger, e) {
+                const target = SpreadJsObj.safeRightClickSelection($trigger, e, materialSpread);
+                return target.hitTestType === GC.Spread.Sheets.SheetArea.viewport || target.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                'create': {
+                    name: '添加工料',
+                    icon: 'fa-sign-in',
+                    callback: function (key, opt) {
+                        // 获取已选清单
+                        changeMaterialTable();
+                        $('#addgl').modal('show');
+                    },
+                    disabled: function (key, opt) {
+                        const sheet = leafXmjSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        const notx = notJoinList.find(function (item) {
+                            return item.gcl_id === select.gcl_id && item.xmj_id === select.id && (select.mx_id === undefined || (select.mx_id !== undefined && select.mx_id === item.mx_id));
+                        });
+                        if (!readOnly && notx === undefined) {
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                },
+                'delete': {
+                    name: '删除工料',
+                    icon: 'fa-remove',
+                    callback: function (key, opt) {
+                        materialSpreadObj.del(materialSpread.getActiveSheet());
+                    },
+                    disabled: function (key, opt) {
+                        const sheet = materialSpread.getActiveSheet();
+                        const select = SpreadJsObj.getSelectObject(sheet);
+                        if (!readOnly && select && materialBase.isEdit(select) === undefined) {
+                            return false;
+                        } else {
+                            return true;
+                        }
+                    }
+                },
+            }
+        });
     }
 
     // 切换清单行,读取所属项目节数据
     ledgerSpread.getActiveSheet().bind(spreadNS.Events.SelectionChanged, function (e, info) {
-        const iOldRow = info.oldSelections[0].row, iNewRow = info.newSelections[0].row;
-        if (iNewRow !== iOldRow) {
-            loadLeafXmjData(iNewRow);
+        if (info.oldSelections !== undefined) {
+            const iOldRow = info.oldSelections[0].row, iNewRow = info.newSelections[0].row;
+            if (iNewRow !== iOldRow) {
+                loadLeafXmjData(iNewRow);
+                SpreadJsObj.resetTopAndSelect(leafXmjSpread.getActiveSheet());
+                loadMaterialData(iNewRow, 0);
+                checkNotJoinMaterialData();
+            }
+        }
+
+    });
+    // 切换项目节数据清单明细行,读取已调用的清单工料数据
+    leafXmjSpread.getActiveSheet().bind(spreadNS.Events.SelectionChanged, function (e, info) {
+        if (info.oldSelections !== undefined) {
+            const iOldRow = info.oldSelections[0].row, iNewRow = info.newSelections[0].row;
+            if (iNewRow !== iOldRow) {
+                const sheet = ledgerSpread.getActiveSheet();
+                const select = SpreadJsObj.getSelectObject(sheet);
+                const index = gclGatherData.indexOf(select);
+                loadMaterialData(index, iNewRow);
+                SpreadJsObj.resetTopAndSelect(materialSpread.getActiveSheet());
+            }
         }
     });
 

+ 1 - 0
app/router.js

@@ -225,6 +225,7 @@ module.exports = app => {
     app.post('/tender/:id/measure/material/:order/save', sessionAuth, tenderCheck, materialCheck, 'materialController.saveBillsData');
     // 调差清单
     app.get('/tender/:id/measure/material/:order/list', sessionAuth, tenderCheck, materialCheck, 'materialController.list');
+    app.post('/tender/:id/measure/material/:order/list/save', sessionAuth, tenderCheck, materialCheck, 'materialController.saveListsData');
 
     // 个人账号相关
     app.get('/profile/info', sessionAuth, 'profileController.info');

+ 68 - 15
app/service/material_list.js

@@ -1,7 +1,7 @@
 'use strict';
 
 /**
- * 期计量 数据模型
+ * 调差清单关联工料表 数据模型
  *
  * @author Mai
  * @date 2018/8/13
@@ -24,29 +24,37 @@ module.exports = app => {
         }
 
         /**
-         * 添加工料
+         * 添加工料清单关联
          * @return {void}
          */
-        async add() {
+        async add(data) {
             if (!this.ctx.tender || !this.ctx.material) {
                 throw '数据错误';
             }
-            const newBills = {
-                tid: this.ctx.tender.id,
-                mid: this.ctx.material.id,
-                in_time: new Date(),
-            };
+            const list = [];
+            for (const mb of data.mb_id) {
+                const newLists = {
+                    tid: this.ctx.tender.id,
+                    mid: this.ctx.material.id,
+                    mb_id: mb,
+                    gcl_id: data.gcl_id,
+                    xmj_id: data.xmj_id,
+                    mx_id: data.mx_id,
+                    in_time: new Date(),
+                };
+                list.push(newLists);
+            }
 
             // 新增工料
-            const result = await this.db.insert(this.tableName, newBills);
-            if (result.affectedRows !== 1) {
+            const result = await this.db.insert(this.tableName, list);
+            if (result.affectedRows === 0) {
                 throw '新增工料数据失败';
             }
-            return await this.getDataById(result.insertId);
+            return await this.getMaterialData(this.ctx.tender.id);
         }
 
         /**
-         * 删除工料
+         * 删除工料清单关联
          * @param {int} id 工料id
          * @return {void}
          */
@@ -59,7 +67,7 @@ module.exports = app => {
         }
 
         /**
-         * 修改工料信息
+         * 修改工料清单关联信息
          * @param {Object} data 工料内容
          * @return {void}
          */
@@ -67,11 +75,56 @@ module.exports = app => {
             if (!this.ctx.tender || !this.ctx.material) {
                 throw '数据错误';
             }
-            delete data.in_time;
             // 判断是否可修改
             return await this.db.update(this.tableName, data);
         }
-    }
 
+        /**
+         * 应用工料清单到其它清单中
+         * @return {void}
+         */
+        async addOther(data) {
+            if (!this.ctx.tender || !this.ctx.material) {
+                throw '数据错误';
+            }
+            const list = [];
+            const select = data.select;
+            for (const mb of data.mx_id) {
+                const newLists = {
+                    tid: this.ctx.tender.id,
+                    mid: this.ctx.material.id,
+                    mb_id: select.mb_id,
+                    gcl_id: select.gcl_id,
+                    xmj_id: select.xmj_id,
+                    mx_id: mb,
+                    quantity: select.quantity,
+                    in_time: new Date(),
+                };
+                list.push(newLists);
+            }
+
+            // 新增工料
+            const result = await this.db.insert(this.tableName, list);
+            if (result.affectedRows === 0) {
+                throw '新增工料数据失败';
+            }
+            return await this.getMaterialData(this.ctx.tender.id);
+        }
+
+        /**
+         * 获取工料清单关联表
+         * @param {int} tid 标段id
+         * @return {void}
+         */
+        async getMaterialData(tid) {
+            const sql = 'SELECT ml.`id`, mb.`code`, mb.`name`, mb.`unit`, ml.`quantity`, ml.`mb_id`, ml.`gcl_id`, ml.`xmj_id`, ml.`mx_id`, ml.`tid`' +
+                ' FROM ' + this.tableName + ' as ml' +
+                ' LEFT JOIN ' + this.ctx.service.materialBills.tableName + ' as mb' +
+                ' ON ml.`mb_id` = mb.`id`' +
+                ' WHERE ml.`tid` = ?';
+            const sqlParam = [tid];
+            return await this.db.query(sql, sqlParam);
+        }
+    }
     return MaterialList;
 };

+ 26 - 0
app/service/material_list_notjoin.js

@@ -0,0 +1,26 @@
+'use strict';
+
+/**
+ * 不参与调差-清单关联表 数据模型
+ *
+ * @author Mai
+ * @date 2018/8/13
+ * @version
+ */
+
+
+module.exports = app => {
+    class MaterialListNotJoin extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'material_list_notjoin';
+        }
+    }
+    return MaterialListNotJoin;
+};

+ 5 - 2
app/view/material/list.ejs

@@ -36,7 +36,9 @@
                                 <a class="nav-link active" data-toggle="tab" href="#xmujie" role="tab">清单明细</a>
                             </li>
                             <li class="ml-auto">
-                                <a class="btn btn-sm btn-primary" href="#">应用调差工料至其他清单明细</a>
+                                <% if (!material.readOnly) { %>
+                                <button class="btn btn-sm btn-primary" id="user_all_material">应用调差工料至其他清单明细</button>
+                                <% } %>
                             </li>
                         </ul>
                     </div>
@@ -67,7 +69,8 @@
 <script>
     const materialType = JSON.parse('<%- materialType %>');
     const materialBillsData = JSON.parse('<%- JSON.stringify(materialBillsData) %>');
-    const materialListData = JSON.parse('<%- JSON.stringify(materialListData) %>');
+    let materialListData = JSON.parse('<%- JSON.stringify(materialListData) %>');
+    const notJoinList = JSON.parse('<%- JSON.stringify(materialNotJoinListData) %>');
     const ledger = JSON.parse('<%- JSON.stringify(ledger) %>');
     const curLedgerData = JSON.parse('<%- JSON.stringify(curLedgerData) %>');
     const pos = JSON.parse('<%- JSON.stringify(pos) %>');

+ 44 - 0
app/view/material/list_modal.ejs

@@ -0,0 +1,44 @@
+<% if (!material.readOnly) { %>
+<!--添加调差工料-->
+<div class="modal fade" id="addgl" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">选择调差工料</h5>
+            </div>
+            <div class="modal-body">
+                <div class="input-group input-group-sm mb-2">
+                    <input type="text" class="form-control" name="search" id="search_input" placeholder="输入 工料编号 / 名称 检索" aria-describedby="button-addon2">
+                    <div class="input-group-append">
+                        <button class="btn btn-outline-secondary" type="button" id="search_btn"><i class="fa fa-search"></i></button>
+                    </div>
+                </div>
+                <div class="modal-height-300">
+                    <table class="table table-sm table-bordered">
+                        <thead>
+                        <tr class="text-center"><th>基数</th><th>选择</th><th>编号</th><th>名称</th><th>单位</th><th>规格</th></tr>
+                        </thead>
+                        <tbody id="materialBills">
+                        <% for (const [index,m] of materialBillsData.entries()) { %>
+                        <tr class="table-secondary">
+                            <td><%= index+1 %></td>
+                            <td><input type="checkbox" checked disabled value="<%= m.id %>"></td>
+                            <td><%= m.code %></td>
+                            <td><%= m.name %></td>
+                            <td><%= m.unit %></td>
+                            <td><%= m.spec %></td>
+                        </tr>
+                        <% } %>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary" id="add_material_bill">确定添加</button>
+            </div>
+        </div>
+    </div>
+</div>
+<% } %>
+<% include ./audit_modal.ejs %>